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

Я пытаюсь (и не могу) внедрить шаблон Потребитель-производитель в Java с учетом следующих ограничений:

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

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

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

  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, были жалкими сбоями.

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

Ответы [ 2 ]

4 голосов
/ 21 марта 2012

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

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

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

2 голосов
/ 21 марта 2012

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...