您应该在哪里使用 BlockingQueue 实现而不是简单队列实现?

2022-01-21 00:00:00 queue java

我想我应该从

您应该在哪里使用 BlockingQueue 实现而不是简单队列实现?

Where should you use BlockingQueue Implementations instead of Simple Queue Implementations ?

BlockingQueue 相对于队列实现的优点/缺点是什么,考虑到速度、并发性或其他不同的属性,例如是时候访问最后一个元素了.

我用过这两种队列.我知道阻塞队列通常用于并发应用程序.我正在编写简单的 ByteBuffer 池,我需要一些 ByteBuffer 对象的占位符.我需要最快的、线程安全的队列实现.甚至还有像 ArrayList 这样的 List 实现,它对元素具有恒定的访问时间.

I have used both kind of Queues. I know that Blocking Queue is normally used in concurrent application. I was writing simple ByteBuffer pool where I needed some placeholder for ByteBuffer objects. I needed fastest , thread safe queue implementation. Even there are List implementations like ArrayList which has constant access time for elements.

任何人都可以讨论 BlockingQueue 与 Queue 与 List 实现的优缺点吗?

Can anyone discuss about pros and cons of BlockingQueue vs Queue vs List implementations?

目前我使用 ArrayList 来保存这些 ByteBuffer 对象.

Currently I have used ArrayList to hold these ByteBuffer objects.

我应该使用哪种数据结构来保存这些对象?

推荐答案

如果你想限制某种请求,容量有限的 BlockingQueue 也很有帮助.使用无界队列,生产者可以远远领先于消费者.这些任务最终会被执行(除非有太多导致OutOfMemoryError),但生产者可能早就放弃了,所以努力就白费了.

A limited capacity BlockingQueue is also helpful if you want to throttle some sort of request. With an unbounded queue, a producers can get far ahead of the consumers. The tasks will eventually be performed (unless there are so many that they cause an OutOfMemoryError), but the producer may long since have given up, so the effort is wasted.

在这种情况下,最好向潜在的生产者发出队列已满的信号,并在失败后迅速放弃.例如,生产者可能是一个 web 请求,用户不想等待太久,即使它在等待时不会消耗很多 CPU 周期,但它正在使用有限的资源,如套接字和一些内存.放弃会让已经排队的任务有更好的机会及时完成.

In situations like these, it may be better to signal a would-be producer that the queue is full, and to give up quickly with a failure. For example, the producer might be a web request, with a user that doesn't want to wait too long, and even though it won't consume many CPU cycles while waiting, it is using up limited resources like a socket and some memory. Giving up will give the tasks that have been queued already a better chance to finish in a timely manner.

关于修改后的问题,我将其解释为什么是在池中保存对象的好集合?"

Regarding the amended question, which I'm interpreting as, "What is a good collection for holding objects in a pool?"

无界LinkedBlockingQueue 对于很多池来说都是不错的选择.但是,根据您的池管理策略,ConcurrentLinkedQueue 也可以工作.

An unbounded LinkedBlockingQueue is a good choice for many pools. However, depending on your pool management strategy, a ConcurrentLinkedQueue may work too.

在池应用程序中,阻塞放置"是不合适的.控制队列的最大大小是池管理器的工作——它决定何时为池创建或销毁资源.池的客户端从池中借用和归还资源.添加新对象,或将以前借用的对象返回到池中应该是快速、非阻塞的操作.因此,有限容量队列对于池来说不是一个好的选择.

In a pooling application, a blocking "put" is not appropriate. Controlling the maximum size of the queue is the job of the pool manager—it decides when to create or destroy resources for the pool. Clients of the pool borrow and return resources from the pool. Adding a new object, or returning a previously borrowed object to the pool should be fast, non-blocking operations. So, a bounded capacity queue is not a good choice for pools.

另一方面,当从池中检索对象时,大多数应用程序都希望等到资源可用.至少暂时阻塞的获取"操作比忙等待"——反复轮询直到有资源可用更有效.LinkedBlockingQueue 在这种情况下是一个不错的选择.借款人可以使用 采取,或使用poll.

On the other hand, when retrieving an object from the pool, most applications want to wait until a resource is available. A "take" operation that blocks, at least temporarily, is much more efficient than a "busy wait"—repeatedly polling until a resource is available. The LinkedBlockingQueue is a good choice in this case. A borrower can block indefinitely with take, or limit the time it is willing to block with poll.

一种不太常见的情况,即客户端根本不愿意阻塞,但如果池为空,则能够为自己创建资源.在这种情况下,ConcurrentLinkedQueue 是一个不错的选择.这是一个灰色区域,尽可能多地共享资源(例如内存)会很好,但速度更为重要.在更坏的情况下,这会退化为每个线程都有自己的资源实例;那么不用费心尝试在线程之间共享会更有效.

A less common case in when a client is not willing to block at all, but has the ability to create a resource for itself if the pool is empty. In that case, a ConcurrentLinkedQueue is a good choice. This is sort of a gray area where it would be nice to share a resource (e.g., memory) as much as possible, but speed is even more important. In the worse case, this degenerates to every thread having its own instance of the resource; then it would have been more efficient not to bother trying to share among threads.

这两个集合都在并发应用程序中提供了良好的性能和易用性.对于非并发应用程序,ArrayList 很难被击败.即使对于动态增长的集合,LinkedList 的每个元素开销也允许具有一些空槽的 ArrayList 在内存方面保持竞争力.

Both of these collections give good performance and ease of use in a concurrent application. For non-concurrent applications, an ArrayList is hard to beat. Even for collections that grow dynamically, the per-element overhead of a LinkedList allows an ArrayList with some empty slots to stay competitive memory-wise.

相关文章