Производитель-потребитель в Java с переключателем пользовательского интерфейса

Я пытаюсь и не могу реализовать шаблон Producer Consumer в java с учетом следующих ограничений:

  • Производитель создает (а Потребитель потребляет) очередь конечного размера.
  • Существует пользовательский интерфейс с кнопками, переключающими производителя и потребителя по отдельности.
  • Производитель должен производить только тогда, когда очередь не заполнена и кнопка производителя активна,
  • Потребитель должен потреблять только тогда, когда очередь не пуста и кнопка потребителя активна.
  • И производство, и потребление должны быть возможны одновременно. (Так получается, что производство будет минимум максимально возможным по сравнению с потреблением, а иногда и быстрее.)

Моя идея состояла в том, чтобы реализовать буфер как LinkedBlockingQueue конечного размера, чтобы обрабатывать условия, относящиеся к состояниям пустой/полной очереди - он должен блокироваться при попытке поставить в полную очередь или взять из пустой. Затем используйте логическое состояние для производителя и потребителя, запускаемое кнопками. Наконец, используйте цикл while/wait/loop в производителях и потребителях и уведомление в коде для кнопок.

Что-то вроде следующего для стороны производителя:

  while (true) { 
    if (!producing) { wait(); }
    //  generate a bunch of data and and finally        
    //  Save this chunk of data
    buffer.addData(data);
  }

И в коде для кнопки производителя мы одновременно переключаем состояние производства и вызываем метод производителя, который самоуведомляется.

Проблема: как только производитель начинает производство, он так усердно опрашивает, что даже пользовательский интерфейс (реализованный в Swing) теряет отзывчивость. Я могу исправить это, добавив оператор wait(1);, но по разным причинам, не подлежащим обсуждению, это просто неприемлемо. Некоторая задержка неизбежна, но задержка в 1 мс каждый раз при прохождении цикла просто не сработает.

Я также не уверен, что правильно понимаю LinkedBlockingQueue, поскольку, если я позволю очереди заполниться, я все равно потеряю отзывчивость пользовательского интерфейса. Я явно неправильно понимаю, как работают надстроенные операции в Java, поскольку я пробовал несколько подходов, и это самое близкое, что у меня есть; предыдущие подходы, пытавшиеся обрабатывать условия полного/пустого состояния «вручную» без LinkedBlockingQueue, потерпели неудачу.

Любой совет будет принят во внимание. Конечно, то, что я пытаюсь сделать (зафиксировать два условия без чрезмерного опроса), не невозможно, не так ли?


person Novak    schedule 21.03.2012    source источник


Ответы (2)


Это обсуждение включает программу TwoTimer в где javax.swing.Timer увеличивает int с частотой 100 Гц, а java.util.TimerTask выбирает значение с частотой 1 Гц. Вариант хранит образцы в LinkedBlockingQueue, формируя очередь недавней истории. Это не имеет прямого отношения к вашей задаче, но иллюстрирует важное требование к отзывчивому графическому интерфейсу: никогда не блокируйте поток отправки событий. В примере используется invokeLater() для выполнения следующей коллекции.

Также обратите внимание на nextGaussian() для имитации задержки, как показано здесь.

Кроме того, вам может понравиться этот пример, который анимирует очередь геометрических фигур.

person trashgod    schedule 21.03.2012

То, что вы описали, должно работать нормально. Размещение вашего фактического кода (абстрагирование фактического производства и фактического потребления) поможет. Вы сказали

он опрашивает так сильно, что даже пользовательский интерфейс теряет отзывчивость

это означает, что вы неправильно используете LinkedBlockingQueue. Вы не должны повторно опрашивать очередь. Вы должны получить элемент из очереди, обработать его, затем проверить производственный флаг, а также создать и поставить элемент в очередь или ждать() на мониторе, на котором пользовательский интерфейс вызывает notifyAll().

person Jim    schedule 21.03.2012
comment
Но производство и потребление могут быть включены одновременно, но необязательны. Таким образом, только производство может быть разрешено без потребления. Я обновлю с дополнительным кодом завтра. - person Novak; 21.03.2012