在Java中我应该使用哪种并发队列实现?

10 浏览
0 Comments

在Java中我应该使用哪种并发队列实现?

从JavaDocs:\n

    \n

  • ConcurrentLinkedQueue是多个线程共享访问共同集合时的适当选择。此队列不允许 null 元素。
  • \n

  • ArrayBlockingQueue是一个经典的“有界缓冲区”,其中由生产者插入并由消费者提取元素的固定大小数组。该类支持用于排序等待生产者和消费者线程的可选公平策略。
  • \n

  • LinkedBlockingQueue在大多数并发应用程序中通常具有比基于数组的队列更高的吞吐量,但性能较不可预测。
  • \n

\n我有两种情况,一个需要队列支持多个生产者(使用它的线程)和一个消费者,另一个则相反。\n我不明白应该使用哪种实现。有人可以解释一下它们的区别吗?\n另外,在 ArrayBlockingQueue 中的 “可选公平策略” 是什么意思?

0
0 Comments

在Java中,有许多并发队列实现可供选择,选择哪种取决于具体的使用场景和需求。有一个用户在提问中询问应该在Java中使用哪种并发队列实现。

首先,回答者指出问题标题中提到了阻塞队列,但是ConcurrentLinkedQueue并不是一个阻塞队列。Java中的阻塞队列包括ArrayBlockingQueue、DelayQueue、LinkedBlockingDeque、LinkedBlockingQueue、PriorityBlockingQueue和SynchronousQueue。其中,DelayQueue、PriorityBlockingQueue和SynchronousQueue显然不适合用户的目的。LinkedBlockingQueue和LinkedBlockingDeque是相同的,只是后者是双端队列(实现了Deque接口)。

由于ArrayBlockingQueue只在需要限制元素数量时才有用,所以回答者建议使用LinkedBlockingQueue。

用户对此进行了进一步的追问,询问是否LinkedBlockingQueue可以在多个消费者/生产者的场景下对同一对象进行使用。

最后,用户提出了关于ArrayBlockingQueue的优势,以及它是否允许更细粒度的线程排序。

用户的问题是关于Java中并发队列实现的选择问题。问题的原因是用户对不同类型的并发队列实现的用途和优势不清楚。解决方法是给出了不同并发队列实现的说明和建议,以帮助用户根据具体需求选择合适的实现。

0
0 Comments

在Java中,有多种并发队列实现可供选择。选择哪种并发队列取决于你的需求。下面将介绍不同的并发队列实现及其性能特点和阻塞行为。

首先,ArrayBlockingQueue是一个固定大小的队列。如果你设置队列大小为10,并试图插入第11个元素,插入操作将会阻塞,直到另一个线程移除一个元素。公平性问题是指当多个线程同时尝试插入和移除元素时(也就是在队列被阻塞的时期),如何保证公平性。公平算法确保第一个请求的线程是第一个获得执行的线程。否则,一个线程可能会比其他线程等待更长的时间,导致不可预测的行为(有时一个线程会花费几秒钟的时间,因为其他后来启动的线程先被处理)。这种权衡是因为管理公平性需要额外的开销,从而降低吞吐量。

LinkedBlockingQueue和ConcurrentLinkedQueue之间最重要的区别是,如果你从一个空的LinkedBlockingQueue请求元素,你的线程将会等待,直到有元素可用。而ConcurrentLinkedQueue将立即返回一个空队列的行为。

选择哪种取决于你是否需要阻塞行为。如果有多个生产者和一个消费者,那么你可能需要阻塞行为。另一方面,如果有多个消费者和一个生产者,你可能不需要阻塞行为,只需要消费者检查队列是否为空,如果为空则继续执行。

回答是误导性的。LinkedBlockingQueue和ConcurrentLinkedQueue都有poll()方法用于移除队列头部或返回null(不阻塞),以及offer(E e)方法用于插入元素到队列尾部并且不阻塞。区别在于只有LinkedBlockingQueue除了非阻塞操作之外,还有阻塞操作,并且为此付出了一些锁的代价。另一篇回答对此进行了解释。

0
0 Comments

在Java中选择并发队列实现时,有几个考虑因素。首先是锁的使用情况。ConcurrentLinkedQueue不使用任何锁,它在修改时使用CAS(Compare and Swap)操作来检查头/尾节点是否与开始时相同。如果是,则操作成功。如果头/尾节点不同,它会一直尝试直到成功。而LinkedBlockingQueue在任何修改之前都会获取一个锁,因此在执行offer操作时可能会阻塞,直到获取到锁。可以使用带有TimeUnit参数的offer方法来指定在放弃添加之前愿意等待的时间。

其次是锁的公平性。如果实现了公平性,锁的使用顺序将会被保留。这意味着如果线程A进入,然后线程B进入,线程A将先获取到锁。如果没有公平性,实际上无法确定会发生什么。很可能是下一个被调度的线程会获取到锁。

关于使用哪个实现取决于具体情况。作者倾向于使用ConcurrentLinkedQueue,因为生产者将工作放入队列的时间是多样化的。没有很多生产者在同一时刻生产。但是消费者方面更加复杂,因为poll操作不会进入一个良好的休眠状态,需要自己处理。

至于在什么条件下ArrayBlockingQueue优于LinkedBlockingQueue,ArrayBlockingQueue允许更细粒度的排序。

"it will spin around and try again"的意思是,如果CAS操作失败(头/尾节点已经发生变化),则会重新尝试操作,直到成功为止。

0