SynchronousQueue или TransferQueue

В Java 7 появился новый интерфейс TransferQueue в добавлении к уже существующему со времен Java 5 SynchronousQueue. Возникает резонный вопрос — для чего?

Для начала о TransferQueue

В Java 7 появился новый интерфейс TransferQueue и соответствующая реализация LinkedTransferQueue.

TransferQueue расширяет BlockingQueue, который в свою очередь расширяет Queue интерфейс, добавленный в Java 5. BlockingQueue — это очередь, которая может блокировать и потоки Поставщиков (Producer) при добавлении элементов в переполненную очередь, и потоки Потребителей (Consumer), при извлечении из пустой очереди. Основная задача блокирующих очередей — справляться с наплывом данных, которые система не в состоянии обработать за приемлемое время.

TransferQueue развивает эту идею и идет дальше, блокируя поток Поставщика до тех пор, пока элемент не будет извлечен потоком Потребителя. Ключевой метод — transfer() — блокировка происходит до тех пор, пока элемент не перейдет от одного потока к другому.

Существуют дополнительные методы — две формы передачи элементов tryTransfer() — либо блокирующая с таймаутом, либо неблокирующая, но осуществляющая передачу только при наличии ожидающего Потребителя. Так же существует пара вспомогательных методов hasWaitingConsumer() и getWaitingConsumerCount().

Пара слов о SynchronousQueue

Все мы помним о SynchronousQueue, который появился ранее в Java 5, предоставляет очередь размеров в 0 элементов и который так хорошо подходит для передачи элементов между потоками. Эта очередь работает по принципу «один вошел — один вышел». Каждая операция вставки блокирует поток Поставщика до тех пор, пока поток Потребителя не получит элемент из очереди и наоборот, Потребитель будет ждать пока Поставщик не вставит элемент в очередь.

SynchronousQueue более специализированный по сравнению с TransferQueue и это позволяет разработчику решать где использовать обычные блокирующие очереди, а где гарантированную передачу элементов.

SynchronousQueue vs TransferQueue

LinkedTransferQueue совмещает преимущества ConcurrentLinkedQueue, SynchronousQueue (в «справедливом» режиме) и неограниченный LinkedBlockingQueues.

Согласно авторам LinkedTransferQueue (William Scherer, Doug Lea, and Michael Scott Scalable Synchronous Queues) тесты производительности показывают преимущество над существовавшими в Java 5 альтернативами. LinkedTransferQueue выигрывает у SynchronousQueue от 3 до 14 раз в зависимости от «справедливости» режимов (fair/unfair). Поскольку SynchronousQueue используется при передаче задач в ThreadPoolExecutor, то в результате можно ожидать улучшение производительности. Учитывая важность Executor в параллельном программировании, становится понятной важность добавления новой реализации.

SynchronousQueue использует двойные очереди — для ожидания поставщиков и потребителей — соответственно и защищает обе очереди одной блокировкой. LinkedTransferQueue использует CAS операции для реализации неблокирующих алгоритмов и позволяет избежать узкого горлышка, обусловленным синхронизацией.

На этом пока все. Если у вас есть вопросы или комментарии — буду рад их услышать. Присоединяйтесь к беседе! Если вам понравилась статья — делитесь с друзьями, подписывайтесь на блог.

English version of the article: SynchronousQueue VS TransferQueue

Комментарии


Нюансы Java разработки

Этот блог о Java разработке и в деталях описывает наиболее важные темы.

Вернуться назад к списку постов

Подписаться

Поиск по сайту