• 阻塞队列LinkedBlockingQueue和并发队列ConcurrentLinkedQueue


    这两个队列都是线程安全的。

    LinkedBlockingQueue:

    public class LinkedBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable  

    此队列按 FIFO(先进先出)排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列检索操作会获得位于队列头部的元素。

    链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。可选的容量范围构造方法参数作为防止队列过度扩展的一种方法。如果未指定容量,则它等于Integer.MAX_VALUE。除非插入节点会使队列超出容量,否则每次插入后会动态地创建链接节点。

    适用阻塞队列的好处:多线程操作共同的队列时不需要额外的同步,另外就是队列会自动平衡负载,即那边(生产与消费两边)处理快了就会被阻塞掉,从而减少两边的处理速度差距。

    Demo:

    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class Main {
        public static void main(String[] args) {
            // 建立一个装苹果的篮子
            Basket basket =  new Basket();
            ExecutorService service = Executors.newCachedThreadPool();
            Producer producer =  new Producer("生产者001", basket);
            Producer producer2 =  new Producer("生产者002", basket);
            Consumer consumer =  new Consumer("消费者001", basket);
            service.submit(producer);
            service.submit(producer2);
            service.submit(consumer);
            // 程序运行5s后,所有任务停止
            try {
                Thread.sleep(1000 * 5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            service.shutdownNow();
    
        }
    }
    
    /**
     *
     * 定义装苹果的篮子
     *
     */
    class Basket {
        // 篮子,能够容纳3个苹果
        BlockingQueue<String> basket = new LinkedBlockingQueue<String>(3);
        int i=0;
        // 生产苹果,放入篮子
        public void produce() throws InterruptedException {
            // put方法放入一个苹果,若basket满了,等到basket有位置
            i++;
            basket.put("An apple"+i);
        }
    
        // 消费苹果,从篮子中取走
        public String consume() throws InterruptedException {
            // take方法取出一个苹果,若basket为空,等到basket有苹果为止(获取并移除此队列的头部)
            return basket.take();
        }
    }
    
    // 定义苹果生产者
    class Producer implements Runnable {
        private String instance;
        private Basket basket;
    
        public Producer(String instance, Basket basket) {
            this.instance = instance;
            this.basket = basket;
        }
    
        public void run() {
            try {
                while (true) {
                    // 生产苹果
                    System.out.println("生产者准备生产苹果:" + instance);
                    basket.produce();
                    System.out.println("!生产者生产苹果完毕:" + instance);
                    // 休眠300ms
                    Thread.sleep(300);
                }
            } catch (InterruptedException ex) {
                System.out.println("Producer Interrupted");
            }
        }
    }
    
    // 定义苹果消费者
    class Consumer implements Runnable {
        private String instance;
        private Basket basket;
    
        public Consumer(String instance, Basket basket) {
            this.instance = instance;
            this.basket = basket;
        }
    
        public void run() {
            try {
                while (true) {
                    // 消费苹果
                    System.out.println("消费者准备消费苹果:" + instance);
                    System.out.println(basket.consume());
                    System.out.println("!消费者消费苹果完毕:" + instance);
                    // 休眠1000ms
                    Thread.sleep(1000);
                }
            } catch (InterruptedException ex) {
                System.out.println("Consumer Interrupted");
            }
        }
    }
    生产者准备生产苹果:生产者001
    消费者准备消费苹果:消费者001
    生产者准备生产苹果:生产者002
    !生产者生产苹果完毕:生产者002
    !生产者生产苹果完毕:生产者001
    An apple1
    !消费者消费苹果完毕:消费者001
    生产者准备生产苹果:生产者001
    生产者准备生产苹果:生产者002
    !生产者生产苹果完毕:生产者001
    !生产者生产苹果完毕:生产者002
    生产者准备生产苹果:生产者001
    生产者准备生产苹果:生产者002
    消费者准备消费苹果:消费者001
    An apple2
    !生产者生产苹果完毕:生产者001
    !消费者消费苹果完毕:消费者001
    生产者准备生产苹果:生产者001
    消费者准备消费苹果:消费者001
    An apple3
    !消费者消费苹果完毕:消费者001
    !生产者生产苹果完毕:生产者002
    生产者准备生产苹果:生产者002
    消费者准备消费苹果:消费者001
    An apple4
    !消费者消费苹果完毕:消费者001
    !生产者生产苹果完毕:生产者001
    生产者准备生产苹果:生产者001
    消费者准备消费苹果:消费者001
    An apple5
    !消费者消费苹果完毕:消费者001
    !生产者生产苹果完毕:生产者002
    生产者准备生产苹果:生产者002
    Producer Interrupted
    Producer Interrupted
    Consumer Interrupted
    View Code

    ConcurrentLinkedQueue:(http://blog.csdn.net/chenssy/article/details/74853120)

    ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。

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

    代码:

    package com.qhong;
    
    
    import java.util.concurrent.ConcurrentLinkedQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Main {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(2);
    
            executorService.submit(new NoBlockQueue.Producer("producer1"));
            executorService.submit(new NoBlockQueue.Producer("producer2"));
            executorService.submit(new NoBlockQueue.Producer("producer3"));
            executorService.submit(new NoBlockQueue.Consumer("consumer1"));
            executorService.submit(new NoBlockQueue.Consumer("consumer2"));
            executorService.submit(new NoBlockQueue.Consumer("consumer3"));
        }
    }
    class NoBlockQueue {
        private static ConcurrentLinkedQueue<Integer> concurrentLinkedQueue = new ConcurrentLinkedQueue<Integer>();
        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(Thread.currentThread().getName()+"-----"+ name+ " start producer " + i);
                    concurrentLinkedQueue.add(i);
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.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 {
                        System.out.println(Thread.currentThread().getName()+"-----"+name+" Consumer " +  concurrentLinkedQueue.poll());
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    Output:

    pool-1-thread-1-----producer1 start producer 1
    pool-1-thread-2-----producer2 start producer 1
    pool-1-thread-1-----producer1 start producer 2
    pool-1-thread-2-----producer2 start producer 2
    pool-1-thread-1-----producer1 start producer 3
    pool-1-thread-2-----producer2 start producer 3
    pool-1-thread-1-----producer1 start producer 4
    pool-1-thread-2-----producer2 start producer 4
    pool-1-thread-1-----producer1 start producer 5
    pool-1-thread-2-----producer2 start producer 5
    pool-1-thread-2-----producer2 start producer 6
    pool-1-thread-2-----producer2 start producer 7
    pool-1-thread-1-----producer1 start producer 6
    pool-1-thread-2-----producer2 start producer 8
    pool-1-thread-1-----producer1 start producer 7
    pool-1-thread-2-----producer2 start producer 9
    pool-1-thread-1-----producer1 start producer 8
    pool-1-thread-1-----producer1 start producer 9
    pool-1-thread-2-----producer3 start producer 1
    pool-1-thread-1-----consumer1 Consumer 1
    pool-1-thread-1-----consumer1 Consumer 1
    pool-1-thread-1-----consumer1 Consumer 2
    pool-1-thread-1-----consumer1 Consumer 2
    pool-1-thread-1-----consumer1 Consumer 3
    pool-1-thread-1-----consumer1 Consumer 3
    pool-1-thread-1-----consumer1 Consumer 4
    pool-1-thread-1-----consumer1 Consumer 4
    pool-1-thread-1-----consumer1 Consumer 5
    pool-1-thread-1-----consumer2 Consumer 5
    pool-1-thread-1-----consumer2 Consumer 6
    pool-1-thread-1-----consumer2 Consumer 7
    pool-1-thread-1-----consumer2 Consumer 6
    pool-1-thread-1-----consumer2 Consumer 8
    pool-1-thread-1-----consumer2 Consumer 7
    pool-1-thread-1-----consumer2 Consumer 9
    pool-1-thread-1-----consumer2 Consumer 8
    pool-1-thread-1-----consumer2 Consumer 9
    pool-1-thread-1-----consumer3 Consumer 1
    pool-1-thread-1-----consumer3 Consumer null
    pool-1-thread-1-----consumer3 Consumer null
    pool-1-thread-1-----consumer3 Consumer null
    pool-1-thread-1-----consumer3 Consumer null
    pool-1-thread-1-----consumer3 Consumer null
    pool-1-thread-1-----consumer3 Consumer null
    pool-1-thread-1-----consumer3 Consumer null
    pool-1-thread-1-----consumer3 Consumer null
    pool-1-thread-2-----producer3 start producer 2
    pool-1-thread-2-----producer3 start producer 3
    pool-1-thread-2-----producer3 start producer 4
    pool-1-thread-2-----producer3 start producer 5
    pool-1-thread-2-----producer3 start producer 6
    pool-1-thread-2-----producer3 start producer 7
    pool-1-thread-2-----producer3 start producer 8
    pool-1-thread-2-----producer3 start producer 9
    View Code

    http://www.cnblogs.com/linjiqin/archive/2013/05/30/3108188.html

    http://blog.csdn.net/ac903919/article/details/6967728

    http://www.soso.io/article/66762.html

    http://ifeve.com/concurrentlinkedqueue/

    http://www.cnblogs.com/sunshine-2015/p/6067709.html

  • 相关阅读:
    luogu P1019 单词接龙
    luogu P4137 Rmq Problem / mex
    Virtualbox 修改硬盘的序列号等信息 例
    httpHandlers path="*.sky"
    Oracle告Google输了
    %STSADM% -o addsolution -filename AEMediaPlayerWebpart.wsp
    placeholder
    String强制转换为Date,freemarker标签里date数据的显示问题
    eclipse配置JDK和设置编译版本的几种方法
    httpd 系统错误 无法启动此程序,因为计算机中丢失VCRUNTIME140.dll
  • 原文地址:https://www.cnblogs.com/hongdada/p/6142182.html
Copyright © 2020-2023  润新知