Java中几个常用并发队列比较 | Baeldung

解道jdon 2021-05-04 16:49:16
java 队列 比较 并发 常用


在多线程应用程序中,队列需要处理多个并发的生产者-消费者方案。正确选择并发队列对于在我们的算法中实现良好性能至关重要。 

首先,我们将看到阻塞队列和非阻塞队列之间的一些重要区别。然后,我们将看一些实现和最佳实践。

 

BlockingQueue提供了一种简单的线程安全机制。在此队列中,线程需要等待队列的可用性。生产者将在添加元素之前等待可用容量,而消费者将等待直到队列为空。为了实现这种阻塞机制,BlockingQueue接口在常规Queue函数的基础上提供了两个函数:put和take。这些功能等效于标准Queue中的add和remove。

 

ArrayBlockingQueue

此队列在内部使用数组。因此,它是一个有界队列,这意味着它具有固定的大小。适合生产者/消费者比率通常很低情况,我们将耗时的任务分配给多个worker。由于此队列不能无限增长,因此如果出现内存问题,需要将大小限制将作为安全阈值。

ArrayBlockingQueue对put和take操作都使用一个锁。这样可以确保不覆盖条目,但会降低性能。

 

LinkedBlockingQueue

LinkedBlockingQueue使用链表变体,其中每个队列项目是一个新的节点。虽然这使队列在原则上不受限制,但仍然具有Integer.MAX_VALUE的硬限制。我们可以使用构造函数LinkedBlockingQueue(int capacity)设置队列大小。

队列使用不同的锁进行put和take操作。因此两种操作可以并行完成并提高了吞吐量。

由于LinkedBlockingQueue可以是有界的或无界的,为什么我们还要使用ArrayBlockingQueue?每次在队列中添加或删除项目时,LinkedBlockingQueue都需要分配和取消分配节点。因此,如果队列快速增长和快速收缩,则  ArrayBlockingQueue可能是更好的选择。

据说LinkedBlockingQueue的性能是不可预测的。换句话说,我们始终需要剖析我们的方案以确保我们使用正确的数据结构。

 

PriorityBlockingQueue

当我们需要按特定顺序消费数据时,PriorityBlockingQueue是我们的首选解决方案。为此,PriorityBlockingQueue使用基于数组的二进制堆。

尽管在内部使用单个锁定机制,但是take操作可以与put操作同时进行。使用简单的自旋锁可以实现这一点。

一个典型的用例是使用具有不同优先级的任务。我们不希望低优先级的任务代替高优先级的任务。

 

DelayQueue

当使用者只能take过期的数据项目时,我们使用DelayQueue 。有趣的是,它在内部使用PriorityQueue来按数据项目的到期时间对其进行排序。

由于这不是通用队列,因此它无法涵盖ArrayBlockingQueue或LinkedBlockingQueue那样多的场景。例如,我们可以使用此队列来实现一个简单的事件循环,类似于在NodeJS中找到的事件循环。我们将异步任务放在队列中,以便在它们到期时进行后续处理。

 

LinkedTransferQueue

LinkedTransferQueue引入一个transfer 方法。尽管其他队列通常在生产或消费数据项目时阻塞,但LinkedTransferQueue 允许生产者等待数据项目的消费。

当我们需要保证放入队列中的某个特定项目已被消费者take拿走时,可以使用LinkedTransferQueue。同样,我们可以使用此队列实现简单的反压算法。实际上,通过阻止生产者直到消费,消费者可以驱动所产生的消息流。

 

SynchronousQueue

普通队列通常包含许多数据项目,但SynchronousQueue最多始终只有一个项目。换句话说,我们需要将SynchronousQueue视为在两个线程之间交换某些数据的简单方法。

当我们有两个需要访问共享状态的线程时,我们通常将它们与CountDownLatch或其他同步机制同步。通过使用SynchronousQueue,我们可以避免线程的这种手动同步。

 

ConcurrentLinkedQueue

ConcurrentLinkedQueue是本文唯一的非阻塞队列,因此,它提供了一种“免等待”算法,其中add和poll保证是线程安全的,并立即返回。该队列使用CAS(Compare-And-Swap)代替锁。

在内部,它基于Maged M. Michael和Michael L. Scott的简单,快速和实用的非阻塞和阻塞并发队列算法

对于经常禁止使用阻塞数据结构的现代反应系统,它是理想的选择。

另一方面,如果我们的消费者最终陷入循环等待,我们可能应该选择阻塞队列作为更好的选择。

版权声明
本文为[解道jdon]所创,转载请带上原文链接,感谢
https://www.jdon.com/54829

  1. Realization of reactor Kafka through spring boot Webflux
  2. RPC框架设计----Socket与I/0模型
  3. Problems in upgrading from Java 8 to Java 11
  4. RPC framework design -- socket and I / 0 model
  5. RPC框架设计----I/0模型
  6. RPC framework design: I / 0 model
  7. RPC框架设计----NIO编程缓冲区Buffer
  8. RPC框架设计----NIO编程缓冲区Buffer
  9. RPC framework design -- NiO programming buffer
  10. RPC framework design -- NiO programming buffer
  11. Java多线程基础
  12. Java multithreading Foundation
  13. 码农飞升记-00-Java发展历程
  14. Development history of coder-00-java
  15. 码农飞升记-00-Java发展历程
  16. Development history of coder-00-java
  17. Spring and Autumn Moon
  18. Node.js与Spring Boot比较? - Ryan Gleason
  19. Spring WebFlux的明显陷阱 - ŁukaszKyć
  20. Spring创始人Rod大叔对YAML的真实想法
  21. Compare node.js with spring boot- Ryan Gleason
  22. Obvious pitfalls of spring Webflux- Ł ukaszKy ć
  23. Spring founder uncle rod's real thoughts on yaml
  24. 码农飞升记-02-OracleJDK是什么?OracleJDK的版本怎么选择?
  25. What is manong feisheng-02-oracle JDK? How to choose the version of Oracle JDK?
  26. Spring tide surging Xinanjiang
  27. Linux内核软中断
  28. Linux kernel soft interrupt
  29. Linux内核软中断
  30. Linux kernel soft interrupt
  31. Java multithreading Foundation
  32. The construction of Maven private library nexus
  33. I / O stream in Java
  34. JDK 16:Java 16的新功能 - InfoWorld
  35. 在Java中本地进行线程间数据传输的三种方式和源码展示
  36. jdon导致cpu 99%最后tomcat死掉---banq给予回复
  37. 用领域事件模拟AOP注入
  38. JDK 16: new function of Java 16 - InfoWorld
  39. Cartoon: from JVM lock to redis distributed lock
  40. Spring 3.1 终于加入了Cache支持
  41. Prototype与JQuery对比
  42. Three ways of data transmission between threads in Java and source code display
  43. Jdon causes 99% of CPU and Tomcat dies -- banq replies
  44. docker 原理之 user namespace(下)
  45. Simulating AOP injection with domain events
  46. Spring 3.1 finally adds cache support
  47. Comparison between prototype and jquery
  48. User namespace of docker principle (2)
  49. The way to learn java IO stream and XML
  50. Why does a seemingly correct code cause the Dubbo thread pool to be full
  51. 0 基础 Java 自学之路(2021年最新版)
  52. 0 basic Java self study road (latest version in 2021)
  53. c#—基础拾遗(1) 面向对象
  54. C - basic information (1) object oriented
  55. 技术分享|SQL和 NoSQL数据库之间的差异:MySQL(VS)MongoDB
  56. Technology sharing differences between SQL and NoSQL databases: MySQL (VS) mongodb
  57. PHP教程/面向对象-3~构造函数和析构函数
  58. Spring Cloud的Feign客户端入门
  59. 优化Spring Boot应用的Docker打包速度
  60. PHP tutorial / object oriented - 3 ~ constructor and destructor