Exchanger
- это более чистый механизм синхронизации, в то время как SynchronousQueue
дополнительно предлагает все операции стандартной структуры данных очереди.Это означает, что вы можете, например, проверить, какие объекты находятся в очереди, отменить запланированные, но еще не выполненные действия, асинхронно удаляя элементы из очереди и т. Д. - операции, которые Exchanger
не предлагает.Поскольку многие реализации позволяют устанавливать ограничение на размер очереди, вы получаете дополнительный контроль над использованием ресурсов и можете отбрасывать запросы, если очередь растет выше определенного порога.С другой стороны, Exchanger
предлагает двустороннюю связь "из коробки", в то время как одна очередь - только один путь (хотя можно реализовать связь в другом направлении вручную).Поскольку во многих практических ситуациях требуются только отношения между производителями и потребителями, очередь часто лучше из-за более простого понимания API и перечисленных выше дополнительных операций.
В этой статье описывается практический пример использованияExchanger
.Они концентрируются на том, чтобы избежать создания и сбора мусора новых объектов при обмене данными между потоками (в зависимости от реализации, очереди могут выделять записи, когда вы что-то добавляете к ним).Производительность, вероятно, будет зависеть от вашего конкретного случая использования.В примере они используют Exchanger
для эффективности (избегая сбора мусора), но в большинстве случаев (если вам не нужно предоставлять задержки в миллисекундах), выделение объекта или двух не такая большая проблема, и я быпредпочитаю использовать очередь для дополнительного элемента управления, который позволяет.
РЕДАКТИРОВАТЬ: Я проверил источник для Exchanger.java
в Oracle JDK, и он создает временные объекты класса Exchanger.Node
в Exchanger.doExchange()
.Таким образом, кажется, что вопреки тому, что утверждают авторы связанной статьи, Exchanger
не является свободным от выделения.Ни один не (довольно очевидно) LinkedBlockingQueue
.ArrayBlockingQueue
, напротив, не выделяет никаких временных объектов при добавлении к нему элемента.Он только выделяет массив для хранения максимально допустимого количества элементов при его создании, но это всего лишь одноразовая операция.Во время использования он не создает новые объекты, поэтому с точки зрения чистого GC он должен быть лучше, чем Exchanger
.