JAVA阻塞队列LinkedBlockingQueue 以及非阻塞队列ConcurrentLinkedQueue 的区别
来源:互联网 发布:打印机排版软件 编辑:程序博客网 时间:2024/05/17 08:46
阻塞队列:线程安全
按 FIFO(先进先出)排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列检索操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。
注意:
1、必须要使用take()方法在获取的时候达成阻塞结果
2、使用poll()方法将产生非阻塞效果
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingDeque;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.TimeUnit; public class BlockingDeque { //阻塞队列,FIFO private static LinkedBlockingQueue<Integer> concurrentLinkedQueue = new LinkedBlockingQueue<Integer>(); public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.submit(new Producer("producer1")); executorService.submit(new Producer("producer2")); executorService.submit(new Producer("producer3")); executorService.submit(new Consumer("consumer1")); executorService.submit(new Consumer("consumer2")); executorService.submit(new Consumer("consumer3")); } static class Producer implements Runnable { private String name; public Producer(String name) { this.name = name; } public void run() { for (int i = 1; i < 10; ++i) { System.out.println(name+ " 生产: " + i); //concurrentLinkedQueue.add(i); try { concurrentLinkedQueue.put(i); Thread.sleep(200); //模拟慢速的生产,产生阻塞的效果 } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } static class Consumer implements Runnable { private String name; public Consumer(String name) { this.name = name; } public void run() { for (int i = 1; i < 10; ++i) { try { //必须要使用take()方法在获取的时候阻塞 System.out.println(name+"消费: " + concurrentLinkedQueue.take()); //使用poll()方法 将产生非阻塞效果 //System.out.println(name+"消费: " + concurrentLinkedQueue.poll()); //还有一个超时的用法,队列空时,指定阻塞时间后返回,不会一直阻塞 //但有一个疑问,既然可以不阻塞,为啥还叫阻塞队列? //System.out.println(name+" Consumer " + concurrentLinkedQueue.poll(300, TimeUnit.MILLISECONDS)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
得到:
producer2 生产: 1
producer1 生产: 1
producer1 生产: 2
producer2 生产: 2
producer1 生产: 3
producer2 生产: 3
producer1 生产: 4
producer2 生产: 4
producer1 生产: 5
producer2 生产: 5
producer1 生产: 6
producer2 生产: 6
producer2 生产: 7
producer1 生产: 7
producer2 生产: 8
producer1 生产: 8
producer2 生产: 9
producer1 生产: 9
producer3 生产: 1
consumer1消费: 1
consumer1消费: 1
consumer1消费: 2
consumer1消费: 2
consumer1消费: 3
consumer1消费: 3
consumer1消费: 4
consumer1消费: 4
consumer1消费: 5
consumer2消费: 5
consumer2消费: 6
consumer2消费: 6
consumer2消费: 7
consumer2消费: 7
consumer2消费: 8
consumer2消费: 8
consumer2消费: 9
consumer2消费: 9
consumer3消费: 1
producer3 生产: 2
consumer3消费: 2
producer3 生产: 3
consumer3消费: 3
producer3 生产: 4
consumer3消费: 4
producer3 生产: 5
consumer3消费: 5
producer3 生产: 6
consumer3消费: 6
producer3 生产: 7
consumer3消费: 7
producer3 生产: 8
consumer3消费: 8
producer3 生产: 9
consumer3消费: 9
非阻塞队列
基于链接节点的、无界的、线程安全。此队列按照 FIFO(先进先出)原则对元素进行排序。队列的头部 是队列中时间最长的元素。队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部,队列检索操作从队列头部获得元素。当许多线程共享访问一个公共 collection 时,ConcurrentLinkedQueue 是一个恰当的选择。此队列不允许 null 元素。
import java.util.concurrent.ConcurrentLinkedQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingDeque;import java.util.concurrent.TimeUnit;public class NoBlockQueue { private static ConcurrentLinkedQueue<Integer> concurrentLinkedQueue = new ConcurrentLinkedQueue<Integer>(); public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.submit(new Producer("producer1")); executorService.submit(new Producer("producer2")); executorService.submit(new Producer("producer3")); executorService.submit(new Consumer("consumer1")); executorService.submit(new Consumer("consumer2")); executorService.submit(new Consumer("consumer3")); } static class Producer implements Runnable { private String name; public Producer(String name) { this.name = name; } public void run() { for (int i = 1; i < 10; ++i) { System.out.println(name+ " start producer " + i); concurrentLinkedQueue.add(i); try { Thread.sleep(20); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //System.out.println(name+"end producer " + i); } } } static class Consumer implements Runnable { private String name; public Consumer(String name) { this.name = name; } public void run() { for (int i = 1; i < 10; ++i) { try { System.out.println(name+" Consumer " + concurrentLinkedQueue.poll()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // System.out.println(); // System.out.println(name+" end Consumer " + i); } } } }
得到:
producer1 start producer 1
producer2 start producer 1
producer1 start producer 2
producer2 start producer 2
producer1 start producer 3
producer2 start producer 3
producer1 start producer 4
producer2 start producer 4
producer1 start producer 5
producer2 start producer 5
producer1 start producer 6
producer2 start producer 6
producer1 start producer 7
producer2 start producer 7
producer1 start producer 8
producer2 start producer 8
producer1 start producer 9
producer2 start producer 9
producer3 start producer 1
consumer1 Consumer 1
consumer1 Consumer 1
consumer1 Consumer 2
consumer1 Consumer 2
consumer1 Consumer 3
consumer1 Consumer 3
consumer1 Consumer 4
consumer1 Consumer 4
consumer1 Consumer 5
consumer2 Consumer 5
consumer2 Consumer 6
consumer2 Consumer 6
consumer2 Consumer 7
consumer2 Consumer 7
consumer2 Consumer 8
consumer2 Consumer 8
consumer2 Consumer 9
consumer2 Consumer 9
consumer3 Consumer 1
consumer3 Consumer null
consumer3 Consumer null
consumer3 Consumer null
consumer3 Consumer null
consumer3 Consumer null
consumer3 Consumer null
consumer3 Consumer null
consumer3 Consumer null
producer3 start producer 2
producer3 start producer 3
producer3 start producer 4
producer3 start producer 5
producer3 start producer 6
producer3 start producer 7
producer3 start producer 8
producer3 start producer 9
在并发编程中,一般推荐使用阻塞队列,这样实现可以尽量地避免程序出现意外的错误。阻塞队列使用最经典的场景就是socket客户端数据的读取和解析,读取数据的线程不断将数据放入队列,然后解析线程不断从队列取数据解析。还有其他类似的场景,只要符合生产者-消费者模型的都可以使用阻塞队列。
使用非阻塞队列,虽然能即时返回结果(消费结果),但必须自行编码解决返回为空的情况处理(以及消费重试等问题)。
另外他们都是线程安全的,不用考虑线程同步问题。
- JAVA阻塞队列LinkedBlockingQueue以及非阻塞队列ConcurrentLinkedQueue区别
- (原创)JAVA阻塞队列LinkedBlockingQueue 以及非阻塞队列ConcurrentLinkedQueue 的区别
- JAVA阻塞队列LinkedBlockingQueue 以及非阻塞队列ConcurrentLinkedQueue 的区别
- JAVA阻塞队列LinkedBlockingQueue 以及非阻塞队列ConcurrentLinkedQueue 的区别
- 并发队列ConcurrentLinkedQueue与阻塞队列LinkedBlockingQueue的区别
- 非阻塞队列ConcurrentLinkedQueue与阻塞队列LinkedBlockingQueue原理探究
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用的实例
- 并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue 区别 和 使用场景总结
- java阻塞队列以及非阻塞队列
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue使用场景总结
- 转 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue使用场景总结
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
- 自定义Emmet代码块
- 我来CSDN的第一篇博客
- Linux系统中的EOT和EOF
- WEBAPI querySelector以及queryselectorAll方法详解
- 安卓自定义View----实现TextView可设置drawable宽高度
- JAVA阻塞队列LinkedBlockingQueue 以及非阻塞队列ConcurrentLinkedQueue 的区别
- log4j.properties 详解
- Gym
- 线段树入门(一)
- 前缀式计算
- 数据分析与数据挖掘的区别
- Ubantu安装Vim(VirtualBox虚拟机)
- Nginx学习之十二-负载均衡-加权轮询策略剖析
- 几种去重算法的实现