SynchronousQueue или TransferQueue
В Java 7 появился новый интерфейс TransferQueue в добавлении к уже существующему со времен Java 5 SynchronousQueue. Возникает резонный вопрос — для чего?
Оглавление
- Для начала о TransferQueue
- Пара слов о SynchronousQueue
- SynchronousQueue vs TransferQueue
Для начала о 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 — SynchronousQueue VS TransferQueue
Похожие статьи
Комментарии
Если у вас есть вопросы или комментарии — буду рад их услышать — присоединяйтесь к беседе!
Нюансы Java разработки
Блог о Java разработке и в деталях описывает наиболее интересные темы