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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/358457/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 13:48:53  来源:igfitidea点击:

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

javaqueue

提问by Vaibhav Kamble

I think I shall reframe my question from

我想我应该重新定义我的问题

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

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

to

What are the advantages/disadvantages of BlockingQueue over Queue implementations taking into consideration aspects like speed,concurrency or other properties which vary e.g. time to access last element.

考虑到速度、并发性或其他属性(例如访问最后一个元素的时间)等方面,BlockingQueue 相对于队列实现的优点/缺点是什么。

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.

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

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

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

Currently I have used ArrayList to hold these ByteBuffer objects.

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

Which data structure shall I use to hold these objects?

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

采纳答案by erickson

A limited capacity BlockingQueueis 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.

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

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.

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



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

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

An unbounded LinkedBlockingQueueis a good choice for many pools. However, depending on your pool management strategy, a ConcurrentLinkedQueuemay work too.

无界LinkedBlockingQueue是许多池的不错选择。但是,根据您的池管理策略,aConcurrentLinkedQueue也可能有效。

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.

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

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 LinkedBlockingQueueis a good choice in this case. A borrower can block indefinitely with take, or limit the time it is willing to block with poll.

另一方面,从池中检索对象时,大多数应用程序都希望等到资源可用。至少暂时阻塞的“获取”操作比“忙等待”(重复轮询直到资源可用)高效得多。该LinkedBlockingQueue是个不错的选择在这种情况下。借款人可以无限期地阻止take,或限制它愿意阻止的时间poll

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 ConcurrentLinkedQueueis 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.

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

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

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

回答by Eugene Yokota

You would see BlockingQueuein multi-threaded situations. For example you need pass in a BlockingQueueas a parameter to create ThreadPoolExecutorif you want to create one using constructor. Depending on the type of queue you pass in the executor could act differently.

您会BlockingQueue在多线程情况下看到。例如BlockingQueueThreadPoolExecutor如果您想使用构造函数创建一个,则需要传入 a作为参数来创建。根据您在执行程序中传递的队列类型,可能会有不同的行为。

回答by mrts

BlockingQueueis also useful for serializing parallel operations that depend on each other.

BlockingQueue对于序列化相互依赖的并行操作也很有用。

To bring a concrete (albeit somewhat arbitrary) example, hereis a parallel test for a real-time patient queue web application where callInPatient()needs to launch in parallel with registerPatientToAppointment(), but needs to wait until registerPatientToAppointment()is completed before executing callPatientInAtDoctorsOffice():

举一个具体的(虽然有点武断)的例子,这里是一个实时患者队列 Web 应用程序的并行测试,它callInPatient()需要与 并行启动registerPatientToAppointment(),但需要等到registerPatientToAppointment()完成后再执行callPatientInAtDoctorsOffice()

public class ClinicPatientQueueAppTest extends ParallelTest {

    private static final BlockingQueue WAIT_FOR_REGISTRATION_QUEUE = new ArrayBlockingQueue(2);

    @Test
    public void callInPatient() {
        loginToDoctorsOffice("user", "password");
        waitUntilRegistrationCompleted();  // <--
        callPatientInAtDoctorsOffice();
    }

    @Test
    public void registerPatientToAppointment() {
        registerPatientAtRegistrationKiosk("Patient Peter");
        notifyRegistrationCompleted(); // <--
    }

    private void waitUntilRegistrationCompleted() {
        WAIT_FOR_REGISTRATION_QUEUE.take();
    }

    private void notifyRegistrationCompleted() {
        WAIT_FOR_REGISTRATION_QUEUE.put(this);
    }

}

回答by atish shimpi

It is a Queueimplementation that additionally supports operations that

这是一个Queue额外支持操作的实现

wait for the queue to become non-empty when retrieving an element,

检索元素时等待队列变为非空,

and

wait for space to become available in the queue when storing an element.

存储元素时,等待队列中有可用空间。

If you required above functionality will be followed by your Queueimplementation then use Blocking Queue

如果您需要上述功能将跟随您的Queue实现然后使用Blocking Queue