Ответ 1
Нет, методы не нужно синхронизировать, и вам не нужно определять какие-либо методы; они уже находятся в ConcurrentLinkedQueue, просто используйте их. ConcurrentLinkedQueue делает все блокировки и все, что вам нужно внутренне; ваш продюсер просто предлагает материал в очередь, и ваши потребители опросят его.
Сначала создайте свою очередь:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
Теперь, когда вы создаете свои объекты-производители/потребители, переходите в очередь, чтобы они могли куда-то помещать свои объекты (вместо этого вы могли бы использовать установщик для этого, но я предпочитаю делать такие вещи в конструкторе ):
YourProducer producer = new YourProducer(queue);
и
YourConsumer consumer = new YourConsumer(queue);
и добавьте материал в ваш продюсер:
queue.offer(myObject);
и напишите в своем потребителе (если очередь пуста, poll() вернет null, поэтому проверьте его):
YourObject myObject = queue.poll();
Подробнее см. Javadoc
EDIT:
Если вам нужно заблокировать ожидание очереди, чтобы она не была пустой, вы, вероятно, захотите использовать LinkedBlockingQueue и использовать(). Однако LinkedBlockingQueue имеет максимальную емкость (по умолчанию Integer.MAX_VALUE - более двух миллиардов) и, следовательно, может быть или не быть подходящим в зависимости от ваших обстоятельств.
Если у вас есть только один поток, помещающий материал в очередь, а другой поток, принимающий данные из очереди, ConcurrentLinkedQueue, вероятно, перебор. Это больше, когда вы можете иметь сотни или даже тысячи потоков, обращающихся к очереди в одно и то же время. Ваши потребности, вероятно, будут выполнены с помощью:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
Кроме того, он блокирует экземпляр (очередь), поэтому вы можете синхронизировать свою очередь, чтобы обеспечить атомарность составных операций (как объяснил Джаред). Вы НЕ МОЖЕТЕ делать это с помощью ConcurrentLinkedQueue, поскольку все операции выполняются БЕЗ блокировки на экземпляре (с использованием переменных java.util.concurrent.atomic). Вам не нужно делать это, если вы хотите заблокировать, пока очередь пуста, потому что poll() просто возвращает значение null, пока очередь пуста, а poll() является атомарным. Проверьте, возвращает ли poll() значение null. Если да, подождите(), а затем повторите попытку. Не нужно блокировать.
В конце концов:
Честно говоря, я бы просто использовал LinkedBlockingQueue. Это все еще слишком много для вашего приложения, но вероятность того, что он будет работать нормально. Если он недостаточно эффективен (PROFILE!), Вы всегда можете попробовать что-то еще, и это означает, что вам не нужно иметь дело с ЛЮБОЙ синхронизированной информацией:
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();
queue.put(myObject); // Blocks until queue isn't full.
YourObject myObject = queue.take(); // Blocks until queue isn't empty.
Все остальное - то же самое. Положите, вероятно, не будет блокировать, потому что вы вряд ли ставите два миллиарда объектов в очередь.