SynchronousQueue Vs Exchanger

В чем разница между Exchanger и SynchronousQueue? И сценарии, в которых каждый из них может быть использован? Какой из них лучше? (Lock wise?)

Ответ 1

An Exchanger является более чистым механизмом синхронизации, а SynchronousQueue дополнительно предлагает все операции стандартной структуры данных очереди. Это означает, что вы можете, например, проверить, какие объекты находятся в очереди, отменить запланированные, но еще не выполненные действия, удалив элементы из очереди асинхронно и т.д. - операции Exchanger не предлагают. Поскольку многие реализации позволяют устанавливать ограничение на размер очереди, вы получаете дополнительный контроль над своим использованием ресурсов и можете отбрасывать запросы, если очередь растет выше определенного порога. С другой стороны, Exchanger предлагает двустороннюю связь из коробки, в то время как одиночная очередь - это всего лишь один способ (хотя можно реализовать связь в другом направлении вручную). Поскольку многие практические ситуации требуют только отношений между производителями и потребителями, очередь часто бывает лучше из-за более простого понимания API и дополнительных операций, перечисленных выше.

В этой статье описывается практическое использование для Exchanger. Они концентрируются на том, чтобы не создавать и мусор собирать новые объекты при общении между потоками (в зависимости от реализации, очереди могут выделять записи, когда вы добавляете что-то к ним). Производительность, вероятно, будет зависеть от вашего конкретного варианта использования. В этом примере они используют Exchanger для эффективности (избегая сбора мусора), но в большинстве случаев (если вам не нужно предоставлять субмиллисекундные задержки) выделение одного или двух объектов не является такой большой проблемой, и я бы предпочитают использовать очередь для дополнительного контроля, который он позволяет.

EDIT: Я проверил источник Exchanger.java в Oracle JDK и создал временные объекты класса Exchanger.Node в Exchanger.doExchange(). Таким образом, кажется, что в отличие от того, что авторы связанного состояния статьи, Exchanger не является бесплатным. Ни то, ни другое (довольно очевидно) LinkedBlockingQueue. ArrayBlockingQueue, напротив, не выделяет никаких временных объектов, когда к нему добавляется элемент. Он выделяет только массив для хранения максимально допустимого количества элементов при его создании, но это всего лишь одноразовая операция. Во время использования он не создает новые объекты, поэтому с точки зрения чистого GC он должен быть лучше, чем Exchanger.

Ответ 2

Сфокусируйтесь на ключевом пункте. Обменник: есть точка рандеву, где две нити могут обмениваться объектами SynchQueue: есть очередь! Один поток ставит и ждет, пока не появится другой поток Exchanger - это своего рода двунаправленный SyncQueue