Exchanger 和 SynchronousQueue 有什么区别?它们各自可以用于哪些场景?从性能角度来看,哪个更好?(锁方面呢?)
Exchanger 和 SynchronousQueue 有什么区别?它们各自可以用于哪些场景?从性能角度来看,哪个更好?(锁方面呢?)
Exchanger
更像是纯同步机制,而 SynchronousQueue
另外提供了标准队列数据结构的所有操作。这意味着您可以查看队列中有哪些对象,通过异步移除队列中的项目取消已计划但尚未执行的操作等 - 这些是 Exchanger
不提供的操作。由于许多实现允许设置队列大小的限制,因此您可以对资源使用进行附加控制,并且如果队列增长到某个特定阈值,则可以丢弃请求。另一方面,Exchanger
提供了两种方式的通信,而单个队列仅为单向(虽然可以手动实现在另一个方向上的通信)。由于许多实际情况只需要生产者和消费者之间的关系,因此队列通常更好,因为其 API 更易于理解,并且具有上述附加操作。
本文描述了Exchanger
的一个实际使用案例。他们专注于在线程间通信时避免创建和垃圾回收新对象(具体实现取决于队列是否在添加内容时分配条目)。性能可能取决于您特定的用例。在示例中,他们使用Exchanger
以提高效率(避免垃圾回收),但在大多数情况下(如果您不必提供亚毫秒级延迟),分配一个或两个对象并不是一个很大的问题,我更喜欢使用队列以获得额外的控制。
编辑:我查看了Oracle JDK中Exchanger.java
的源代码,发现它确实在Exchanger.doExchange()
中创建了Exchanger.Node
类的临时对象。因此,与链接文章的作者所述相反,Exchanger
并不是无分配的。显然,LinkedBlockingQueue
也不是。相比之下,ArrayBlockingQueue
在将项目附加到其中时不会分配任何临时对象。它只在创建时分配一个数组以容纳允许的最大元素数,但这只是一次性操作。在使用过程中,它不会创建新对象,因此从纯GC角度来看,它应该比Exchanger
更好。
LinkedBlockingQueue
需要Node
对象,它们保存其有效负载以及对下一个链接项的引用。ArrayBlockingQueue
不需要这样的包装器,但与LinkedBlockingQueue
相比,它必须预先为其最大大小分配数组。这是一次性操作,通常没有问题,但是确实需要分配。因此,队列可能会导致每个项目额外的分配,但不一定需要。现在,我检查了Exchanger
的代码,它实际上确实创建临时的Node
对象。文章的作者似乎是完全错误的。 - Michał KosmulskiExchanger
具有双向优势,所以我想这就是利润所在。但是,由于其内部工作原理,一些队列和Exchanger
都会创建一些临时对象。 - Michał KosmulskiExchanger.java
的源代码,发现在Exchanger.doExchange()
方法中会创建Exchanger.Node
类的临时对象。 - Michał KosmulskiSynchronousQueue
并没有以有意义的方式实现任何类似队列的操作。 - undefined让我们聚焦于重点...
Exchanger是一种双向的SyncQueue。