并发队列对比之一: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));
    }
  
}
原文地址:https://www.cnblogs.com/duanxz/p/2721290.html