zoukankan      html  css  js  c++  java
  • 并发队列对比之二:LinkedBlockingQueue和ArrayBlockingQueue性能对比

    回顾下,LinkedBlockingQueue和ArrayBlockingQueue在实现上不同点有:

    1、ArrayBlockingQueue使用数组存储数据,LinkedBlockingQueue使用单向链表存储数据;

    2、ArrayBlockingQueue使用一个可重入锁和这个锁生成的两个条件对象进行并发控制(classic two-condition algorithm),而LinkedBlockingQueue有2个锁,写锁和读锁,添加数据和删除数据是可以并行进行的,当然添加数据和删除数据的时候只能有1个线程各自执行。

    一、写入性能对比:

    package com.dxz.queue.linked;
    
    public class Bread {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Bread [name=" + name + "]";
        }
        
    }

    生产者和消费者及测试程序如下:

    package com.dxz.queue.linked;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.CountDownLatch;
    
    public class ProducerArray implements Runnable{  
          
        //容器  
        private final ArrayBlockingQueue<Bread> queue;
        private final CountDownLatch cdl;
          
        public ProducerArray(ArrayBlockingQueue<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.put(bread);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    
    package com.dxz.queue.linked;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class ProducerLinked implements Runnable{  
          
        //容器  
        private final LinkedBlockingQueue<Bread> queue;
        private final CountDownLatch cdl;
          
        public ProducerLinked(LinkedBlockingQueue<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.put(bread);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    
    package com.dxz.queue.linked;
    
    import java.util.concurrent.ArrayBlockingQueue;
    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
            
            
        }
        
        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));
        }  
      
    }

    二、写入及读取性能对比:

    package com.dxz.queue.linked;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.CountDownLatch;
    
    public class ConsumerArray implements Runnable{  
          
        //容器  
        private final ArrayBlockingQueue<Bread> queue; 
        private final CountDownLatch cdl;
        private int consumeCount = 0;
          
        public ConsumerArray(ArrayBlockingQueue<Bread> queue, CountDownLatch cdl){  
            this.queue = queue;  
            this.cdl = cdl;
        }  
      
        @Override  
        public void run() {  
            while(true){  
                consume();
            }  
        }  
          
        public void consume(){  
            /** 
             * take()方法和put()方法是对应的,从中拿一个数据,如果拿不到线程挂起 
             * poll()方法和offer()方法是对应的,从中拿一个数据,如果没有直接返回null 
             */  
            try {  
                //Bread bread = queue.take();
                while(consumeCount<1000000) {
                    if(null !=queue.poll()) {
                        consumeCount++;
    //                    System.out.println(consumeCount);
                    }
                }
                cdl.countDown();
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    
    package com.dxz.queue.linked;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class ConsumerLinked implements Runnable{  
          
        //容器  
        private final LinkedBlockingQueue<Bread> queue; 
        private final CountDownLatch cdl;
        private int consumeCount = 0;
          
        public ConsumerLinked(LinkedBlockingQueue<Bread> queue, CountDownLatch cdl){  
            this.queue = queue;  
            this.cdl = cdl;
        }  
      
        @Override  
        public void run() {  
            while(true){  
                consume();
            }  
        }  
          
        public void consume(){  
            /** 
             * take()方法和put()方法是对应的,从中拿一个数据,如果拿不到线程挂起 
             * poll()方法和offer()方法是对应的,从中拿一个数据,如果没有直接返回null 
             */  
            try {  
                //Bread bread = queue.take();
                while(consumeCount<1000000) {
                    if(null !=queue.poll()) {
                        consumeCount++;
    //                    System.out.println(consumeCount);
                    }
                }
                cdl.countDown();
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    
    package com.dxz.queue.linked;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class ClientPutAndTake {  
      
        public static void main(String[] args) throws InterruptedException {  
            int capacity = 10;
            //testArray(capacity);    //put in ArrayBlockingQueue size:=0,and consumed. use time:=3227
            testLinked(capacity);    //put in LinkedBlockingQueue size:=0,and consumed. use time:=459
            
            
        }
        
        private static void testArray(int capacity) throws InterruptedException {
            ArrayBlockingQueue<Bread> queue = new ArrayBlockingQueue<Bread>(capacity);  
            CountDownLatch cdl = new CountDownLatch(11);
            ExecutorService es = Executors.newFixedThreadPool(10);
            long start = System.currentTimeMillis();
            for(int i = 0; i < 10;i++) {
                es.submit(new ProducerArray(queue, cdl));
            }
            Thread consumerThread = new Thread(new ConsumerArray(queue, cdl));
            consumerThread.setDaemon(true);
            consumerThread.start();
            cdl.await();
            long end = System.currentTimeMillis();
            es.shutdown();
            System.out.println("put in ArrayBlockingQueue size:="+queue.size() +",and consumed. use time:="+(end-start));
        }
    
        private static void testLinked(int capacity) throws InterruptedException {
            LinkedBlockingQueue<Bread> queue = new LinkedBlockingQueue<Bread>(capacity);
            CountDownLatch cdl = new CountDownLatch(11);
            ExecutorService es = Executors.newFixedThreadPool(10);
            long start = System.currentTimeMillis();
            for(int i = 0; i < 10;i++) {
                es.submit(new ProducerLinked(queue, cdl));
            }
            Thread consumerThread = new Thread(new ConsumerLinked(queue, cdl));
            consumerThread.setDaemon(true);
            consumerThread.start();
            cdl.await();
            cdl.await();
            long end = System.currentTimeMillis();
            es.shutdown();
            System.out.println("put in LinkedBlockingQueue size:="+queue.size() +",and consumed. use time:="+(end-start));
        }  
      
    }

    阻塞队列的容量越小,冲突概率越大,性能差异越明显。

  • 相关阅读:
    跨库查询数据
    使用StringBuilder与SqlParameter
    sql 循环 随机数创建数据
    sql like N'%...%' 在C#里的写法
    Html 空格与换行
    Python之随机数
    C#之使用随机数
    C#之ArrayList
    Unity之读取本地图片
    GAN(Generative Adversarial Nets)的发展
  • 原文地址:https://www.cnblogs.com/duanxz/p/2720071.html
Copyright © 2011-2022 走看看