最近看《分布式JAVA应用 基础与实践》 里面有一段话
林昊 写道
ArrayBlockingQueue为一个固定大小数组、ReentrantLock以及Condition实现的可阻塞的先进先出的Queue。
除ArrayBlockingQueue之外,BlockingQueue的实现还有LinkedBlockingQueue,LinkedBlockingQueue实现的不同为采用对象的next构成链表的方式存储对象。由于读只操作对头,而写只操作队尾,这里巧妙地采用了两把锁,对于put和offer采用一把锁,对于take和poll则采用另外一把锁,避免了读写时互相竞争锁的情况,因此LinkedBlockingQueue在高并发读写操作都多的情况下,性能会较ArrayBlockingQueue好很多,在遍历以及删除元素则要两把锁都锁住。
除ArrayBlockingQueue之外,BlockingQueue的实现还有LinkedBlockingQueue,LinkedBlockingQueue实现的不同为采用对象的next构成链表的方式存储对象。由于读只操作对头,而写只操作队尾,这里巧妙地采用了两把锁,对于put和offer采用一把锁,对于take和poll则采用另外一把锁,避免了读写时互相竞争锁的情况,因此LinkedBlockingQueue在高并发读写操作都多的情况下,性能会较ArrayBlockingQueue好很多,在遍历以及删除元素则要两把锁都锁住。
乍一看,ArrayBlockingQueue怎么都不如LinkedBlockingQueue性能强大,那ArrayBlockingQueue存在的意义是什么呢?带着这个疑问,自己亲身写了个程序,4个生产者总共生产4* 102,4000*10个产品,4个消费者去消费,队列的最大大小是102,4000,队列分别采用ArrayBQ和LinkedBQ,对比2者消耗时间。(读者可以直接运行该程序得出对比结果)。
import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ArrayBlockingQueue; public class ArrayBlockingQueueVsLinkedBlockingQueue { //队列最大容量 public static final int Q_SIZE = 1024000; //生产者/消费者线程数 public static final int THREAD_NUM = 4; //产品 class Product{ String name; Product(String name){ this.name = name; } } public void test(final BlockingQueue<Product> q) throws InterruptedException{ //生产者线程 class Producer implements Runnable{ @Override public void run() { for(int i=0;i<Q_SIZE*10;i++){ try { q.put(new Product("Lee")); } catch (InterruptedException e) { e.printStackTrace(); } } } }; //消费者线程 class Consumer implements Runnable{ @Override public void run(){ for(int i=0;i<Q_SIZE*10;i++){ try { q.take(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }; //创建生产者 Thread[] arrProducerThread = new Thread[THREAD_NUM]; for(int i=0;i<THREAD_NUM;i++){ arrProducerThread[i] = new Thread(new Producer()); } //创建消费者 Thread[] arrConsumerThread = new Thread[THREAD_NUM]; for(int i=0;i<THREAD_NUM;i++){ arrConsumerThread[i] = new Thread(new Consumer()); } //go! long t1 = System.currentTimeMillis(); for(int i=0;i<THREAD_NUM;i++){ arrProducerThread[i].start(); arrConsumerThread[i].start(); } for(int i=0;i<THREAD_NUM;i++){ arrProducerThread[i].join(); arrConsumerThread[i].join(); } long t2 = System.currentTimeMillis(); System.out.println(q.getClass().getSimpleName() + " cost : " + (t2-t1)); } public static void main(String[] args) throws InterruptedException{ final BlockingQueue<Product> q1 = new LinkedBlockingQueue<Product>(Q_SIZE); final BlockingQueue<Product> q2 = new ArrayBlockingQueue<Product>(Q_SIZE); new ArrayBlockingQueueVsLinkedBlockingQueue().test(q1); new ArrayBlockingQueueVsLinkedBlockingQueue().test(q2); } }
结果令人我意外,ArrayBQ耗时只有LinkedBQ的一半!而且运行的时候ArrayBQ没占满CPU,LinkedBQ却一直占满!
(我的机器 JDK1.6 win7_64 -Xms1024M -Xmx1024M)
(群友的机器)
我这就不懂了,锁竞争更小的LinkedBQ输给了ArrayBQ。。。难道是线程不够多?
于是我把参数改成以下
//队列最大容量 public static final int Q_SIZE = 10240; //生产者/消费者线程数 public static final int THREAD_NUM = 1280;
结果还是ArrayBQ更快。。。
各位技术的朋友,这究竟解释?如果您知道为什么,请务必留言告知鄙人!
我现在唯一的想到的是,LinkedQueue需要建立Node,而且增删时引用的操作比ArrayBQ复杂。ArrayBQ的内部的数组在增删时并不会产生复制的操作,而是当作一个环,增删只会改变putIndex和takeIndex,操作非常简单。
相关推荐
ArrayBlockingQueue源码分析.docx
并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解
3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 PriorityBlockingQueue 7. 同步队列 SynchronousQueue 8. 阻塞双端队列 BlockingDeque 9. ...
数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 PriorityBlockingQueue 7. 同步队列 SynchronousQueue 8. 阻塞双端队列 BlockingDeque 9. 链...
3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 PriorityBlockingQueue 7. 同步队列 Synchronou sQueue 8. 阻塞双端队列 BlockingDeque 9...
主要介绍了java中LinkedBlockingQueue与ArrayBlockingQueue的异同,需要的朋友可以参考下
3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 PriorityBlockingQueue 7. 同步队列 SynchronousQueue 8. 阻塞双端队列 BlockingDeque 9. ...
Java并发编程学习宝典(漫画版),Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习...
3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 PriorityBlockingQueue 7. 同步队列 SynchronousQueue 8. 阻塞双端队列 BlockingDeque 9. ...
1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM .........................
1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................
主要介绍了java并发之ArrayBlockingQueue详细介绍的相关资料,需要的朋友可以参考下
24.2.2. LinkedBlockingQueue 78 24.2.3. LinkedBlockingDeque(双向并发阻塞队列) 84 24.2.4. PriorityBlockingQueue(优先阻塞队列) 85 24.2.5. 总结一下阻塞队列 90 25. Tomcat 如何管理servlet? 90 26. ...
ArrayBlockingQueue LinkedBlockingQueue SynchronousQueue Handler :拒绝处理策略, 线程数量大于最大线程数量就会拒绝处理策略, 四种策略为 ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出...
20.并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解 21.线程池ThreadPoolExecutor实现原理 22.线程池之ScheduledThreadPoolExecutor 23.FutureTask基本操作总结 24.Java中atomic包中的原子操作类...
ArrayBlockingQueue源码解析__动力节点共23页.pdf.zip
V put(K key, V value) Set<K> keySet() Set<Map.Entry,V>> entrySet() 线程不安全,速度快,允许存放null键,null值。 SortedMap 标记: class TreeMap 对键进行排序 HashTable 标记: class ...
主要介绍了详细分析Java并发集合ArrayBlockingQueue的用法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧