并发队列对比之一:ConcurrentLinkedQueue、LinkedBlockingQueue对比分析
关于ConcurrentLinkedQueue和LinkedBlockingQueue:
1.LinkedBlockingQueue是使用锁机制,ConcurrentLinkedQueue是使用CAS算法,虽然LinkedBlockingQueue的底层获取锁也是使用的CAS算法
2.关于取元素,ConcurrentLinkedQueue不支持阻塞去取元素,LinkedBlockingQueue支持阻塞的take()方法,如若大家需要ConcurrentLinkedQueue的消费者产生阻塞效果,需要自行实现
3.关于插入元素的性能,从字面上和代码简单的分析来看ConcurrentLinkedQueue肯定是最快的,但是这个也要看具体的测试场景,我做了两个简单的demo做测试,测试的结果如下,两个的性能差不多,但在实际的使用过程中,尤其在多cpu的服务器上,有锁和无锁的差距便体现出来了,ConcurrentLinkedQueue会比LinkedBlockingQueue快很多:
package com.dxz.queue.linked; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; public class ProducerConcurrnetLinkedQueue implements Runnable{ //容器 private final ConcurrentLinkedQueue<Bread> queue; private final CountDownLatch cdl; public ProducerConcurrnetLinkedQueue(ConcurrentLinkedQueue<Bread> queue, CountDownLatch cdl){ this.queue = queue; this.cdl = cdl; } @Override public void run() { for(int i=0;i<100000; i++){ produce(i); } cdl.countDown(); } public void produce(int i){ /** * put()方法是如果容器满了的话就会把当前线程挂起 * offer()方法是容器如果满的话就会返回false。 */ try { Bread bread = new Bread(); bread.setName(""+i); queue.offer(bread); } catch (Exception e) { e.printStackTrace(); } } } package com.dxz.queue.linked; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; public class ClientPut { public static void main(String[] args) throws InterruptedException { int capacity = 9000000; //testArray(capacity); //put in ArrayBlockingQueue size:=1000000,use time:=624 //testLinked(capacity); //put in LinkedBlockingQueue size:=1000000,use time:=289 testConcurrentLinked(); //put in ConcurrentLinkedQueue size:=1000000,use time:=287 } private static void testArray(int capacity) throws InterruptedException { ArrayBlockingQueue<Bread> queue = new ArrayBlockingQueue<Bread>(capacity); CountDownLatch cdl = new CountDownLatch(10); ExecutorService es = Executors.newFixedThreadPool(10); long start = System.currentTimeMillis(); for(int i = 0; i < 10;i++) { es.submit(new ProducerArray(queue, cdl)); } cdl.await(); long end = System.currentTimeMillis(); es.shutdown(); System.out.println("put in ArrayBlockingQueue size:="+queue.size() +",use time:="+(end-start)); } private static void testLinked(int capacity) throws InterruptedException { LinkedBlockingQueue<Bread> queue = new LinkedBlockingQueue<Bread>(capacity); CountDownLatch cdl = new CountDownLatch(10); ExecutorService es = Executors.newFixedThreadPool(10); long start = System.currentTimeMillis(); for(int i = 0; i < 10;i++) { es.submit(new ProducerLinked(queue, cdl)); } cdl.await(); long end = System.currentTimeMillis(); es.shutdown(); System.out.println("put in LinkedBlockingQueue size:="+queue.size() +",use time:="+(end-start)); } private static void testConcurrentLinked() throws InterruptedException { ConcurrentLinkedQueue<Bread> queue = new ConcurrentLinkedQueue<Bread>(); CountDownLatch cdl = new CountDownLatch(10); ExecutorService es = Executors.newFixedThreadPool(10); long start = System.currentTimeMillis(); for(int i = 0; i < 10;i++) { es.submit(new ProducerConcurrnetLinkedQueue(queue, cdl)); } cdl.await(); long end = System.currentTimeMillis(); es.shutdown(); System.out.println("put in ConcurrentLinkedQueue size:="+queue.size() +",use time:="+(end-start)); } }