zoukankan      html  css  js  c++  java
  • (原创)JAVA阻塞队列LinkedBlockingQueue 以及非阻塞队列ConcurrentLinkedQueue 的区别

    阻塞队列:线程安全

    按 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();
                    }  
    
             }  
         }  
     }  
    }
    
    
    
     

    非阻塞队列

    基于链接节点的、无界的、线程安全。此队列按照 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);  
                }  
            }  
        }  
    } 

    在并发编程中,一般推荐使用阻塞队列,这样实现可以尽量地避免程序出现意外的错误。阻塞队列使用最经典的场景就是socket客户端数据的读取和解析,读取数据的线程不断将数据放入队列,然后解析线程不断从队列取数据解析。还有其他类似的场景,只要符合生产者-消费者模型的都可以使用阻塞队列。

    使用非阻塞队列,虽然能即时返回结果(消费结果),但必须自行编码解决返回为空的情况处理(以及消费重试等问题)。

    另外他们都是线程安全的,不用考虑线程同步问题。

  • 相关阅读:
    IDEA 必要配置
    人工智能能力提升指导总结
    lerna管理前端packages的最佳实践
    【和60】软件即服务的三重境界
    项目章程
    阅读计划
    使用PHP处理文本小技巧
    PHP性能分析
    Ubuntu安装nodejs和yarn
    挖矿病毒
  • 原文地址:https://www.cnblogs.com/starcrm/p/4998067.html
Copyright © 2011-2022 走看看