2016-11-20 3 views
0

У меня есть много производителей, которые производят/покупают объекты разных типов, например. ProducerOfX, ProducerOfY, ConsumerOfX, ConsumerOfY. Производитель помещает объект (X или Y) в очередь и уведомляет своего соответствующего потребителя (ProducerOfX уведомляет только ConsumerOfX).Продюсер потребитель - что блокировать

Для этого мне нужен объект для использования в качестве блокировки. Мой вопрос: создать объект, например. новый X() и заставить оба ProducerOfX и ConsumerOfX вызывать wait/notify?

Будет только одна очередь, и я написал ее для хранения общих объектов MyQueue. Таким образом, многие производители и потребители разделяют эту очередь. Объекты говорят, что X и Y помещаются в одну очередь. Если на нем находится X, то ConsumerOfX пробуждается и удаляет X. То же самое с Y.

Интересно, лучше ли для очереди уведомлять потребителя «У меня теперь есть объект X» или лучше для производителя «Эй, потребители X, я просто положил X в очередь». Я предполагаю, что производители очереди не должны знать о потребителях очереди.

Есть ли более чистый способ сделать это?

+0

Обычно вы используете реализацию параллельной очереди, которая обеспечивает как блокировку (безопасную публикацию, так и на самом деле), так и сторону уведомления. – BeeOnRope

+0

Задача, которую я пытаюсь предпринять, - научить меня многопоточности, и поэтому я не использую ничего из параллельного пакета. – TheCoder

+0

Ваш вопрос непонятен. Если у вас разные типы объектов и разные потребители, используйте две очереди. Возможно, вы должны разбить свой вопрос, по крайней мере, на два: один фокусируется на том, как создать параллельную очередь, и один для вашей идеи о том, что разные созданные/потребительские типы взаимодействуют с одной очередью. Они кажутся мне ортогональными. – BeeOnRope

ответ

0

Это зависит от реализации. Если для разных продуктов существуют отдельные очереди, каждая очередь должна быть защищена отдельным объектом блокировки (этот объект блокировки может сама очередь).

Также это зависит, если вы пишете реализацию для очереди, тогда вы можете решить, что объект Lock является частной переменной. При добавлении вы можете проверить, заполнена ли очередь, вы можете выбрать wait для переменной частного замка. Как только любой объект будет потреблен, вы можете вызывать notifyall (или notify, хотя notifyall предпочтительнее) на частном объекте блокировки. Аналогичным образом вы можете иметь логику и notify, если потребители вызывают метод для извлечения элемента из очереди, когда он пуст. Таким образом, ваш класс очереди будет отвечать за блокировку и уведомление с использованием объекта private variable. Поскольку очередь имеет объект private var lovk, то каждый экземпляр очереди будет иметь свой отдельный объект Lock.

Другой способ заключается в том, что очередь является общей очередью, может быть ее не то, кто пишет очередь, тогда вам нужно будет защитить код, вызывающий методы для добавления и выбора. Если у вас есть отдельные очереди для разных продуктов (x, y и т. Д.), Вам понадобятся разные объекты Lock для каждой очереди. Это необходимо для предотвращения взаимоблокировок, это может произойти (если у нас нет объектов блокировки sepatrate), потребительX ожидает, что queueX будет иметь вставленный элемент (как пустой), а другой производительY не получает возможность вставлять в queueY (как его полный). Следовательно, вам нужны отдельные объекты блокировки.

Update

@TheCoder Если у вас есть только один производитель и потребитель как заинтересуют же вида продукции, то одна очередь в порядке. Теперь возникает вопрос об общем объекте, с которым оба должны взаимодействовать. Это зависит от реализации, если вы хотите, чтобы Queue позаботился об этом, Queue может иметь личное поле private Object monitor = new Object(); и может иметь метод, который синхронизируется 0SCи dequeue на «мониторе».

Метод dequeue Если очередь пуста, то вызовите monitor.wait() внутри цикла while до тех пор, пока очередь не будет пуста. Если очередь не пуста, то удалите объект из очереди и вызовите monitor.notifyAll();

Метод enqueue, если очередь равна полному вызову monitor.wait() в цикле while до тех пор, пока очередь не будет заполнена.Если очередь не заполнена, то добавить объект в очереди и вызвать monitor.notifyAll();

Если ваша реализация такой, который вы хотите очереди, чтобы не заботиться о Syncronization, то вы должны иметь общий объект, на котором Producrer и Consumer может синхронизироваться перед вызовом enqueue и dequeue на queue. Этот общий объект может быть экземпляром queue. wait и notifyAll необходимо вызвать внутри синхронизированного блока совместно используемого объекта.

+0

Одна очередь. См. Раздел «Изменить». – TheCoder

+0

Одна очередь, разделяемая между различными потребителями и производителями. Хорошо. У вас есть отдельные потребители для разных продуктов или потребителей, а производители также являются универсальными (любой потребитель может потреблять продукт X, а любой производитель может производить Y)? –

+0

Наличие отдельной очереди может быть не очень хорошей идеей, может случиться, что производитель определенного продукта никогда или редко получает шанс произвести. То же самое может произойти с потребителем конкретного продукта ... –

Смежные вопросы