• Java中的BlockingQueue小结


    BlockingQueue是java.util.concurrent下的主要用来控制线程同步的工具。

    主要的方法是:put、take一对阻塞存取;add、poll一对非阻塞存取。

    插入:

    1) add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则抛出异常,不好

    2) offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false.

    3) put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续, 有阻塞, 放不进去就等待

    读取:

    4) poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null; 取不到返回null

    5) take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止; 阻塞, 取不到就一直等

    其他:

    int remainingCapacity();返回队列剩余的容量,在队列插入和获取的时候,不要瞎搞,数据可能不准, 不能保证数据的准确性

    boolean remove(Object o); 从队列移除元素,如果存在,即移除一个或者更多,队列改变了,返回true

    public boolean contains(Object o); 查看队列是否存在这个元素,存在返回true

    int drainTo(Collection<? super E> c); //移除此队列中所有可用的元素,并将它们添加到给定 collection中。取出放到集合中

    int drainTo(Collection<? super E> c, int maxElements); 和上面方法的区别在于,指定了移动的数量; 取出指定个数放到集合

    BlockingQueue有四个具体的实现类,常用的两种实现类为:

    1、ArrayBlockingQueue:一个由数组支持的有界阻塞队列,规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的。

    2、LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的。

        LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。

    LinkedBlockingQueue和ArrayBlockingQueue区别:

    LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue。

    下面写一个生产者消费者的例子:

    TestBlockingQueueProducer.java:

    package cn.itcast_02_blockingqueue.main;
    
    import java.util.Random;
    import java.util.concurrent.BlockingQueue;
    
    public class TestBlockingQueueProducer implements Runnable {
        BlockingQueue<String> queue;
        Random random = new Random();
    
        public TestBlockingQueueProducer(BlockingQueue<String> queue) {
            this.queue = queue;
        }
    
        @Override
        public void run() {
    
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(random.nextInt(10));
                    String task = Thread.currentThread().getName() + " made a product " + i;
    
                    System.out.println(task);
                    queue.put(task);
                } catch (InterruptedException e) {
                     
                    e.printStackTrace();
                }
    
            }
    
        }
    
    }

    TestBlockingQueueConsumer.java:

    package cn.itcast_02_blockingqueue.main;
    
    import java.util.Random;
    import java.util.concurrent.BlockingQueue;
    
    public class TestBlockingQueueConsumer implements Runnable{  
        BlockingQueue<String> queue; 
        Random random = new Random();
        
        public TestBlockingQueueConsumer(BlockingQueue<String> queue){  
            this.queue = queue;  
        }        
        @Override  
        public void run() {  
            try {  
                Thread.sleep(random.nextInt(10));
                System.out.println(Thread.currentThread().getName()+ " trying...");
                String temp = queue.take();//如果队列为空,会阻塞当前线程  
                System.out.println(Thread.currentThread().getName() + " get a job " +temp);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }

    TestBlockingQueue.java:

    package cn.itcast_02_blockingqueue.main;
    
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class TestBlockingQueue {
        
        public static void main(String[] args) {
            BlockingQueue<String> queue = new LinkedBlockingQueue<String>(2);
            // BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
            // 不设置的话,LinkedBlockingQueue默认大小为Integer.MAX_VALUE
            // BlockingQueue<String> queue = new ArrayBlockingQueue<String>(2);
            TestBlockingQueueConsumer consumer = new TestBlockingQueueConsumer(queue);
            TestBlockingQueueProducer producer = new TestBlockingQueueProducer(queue);
            for (int i = 0; i < 5; i++) {
                new Thread(producer, "Producer" + (i + 1)).start();
            }
            for (int i = 0; i < 5; i++) {
                new Thread(consumer, "Consumer" + (i + 1)).start();
            }
            
            //new Thread(producer, "Producer" + (5)).start();
        }
    }

    运行结果:

    Consumer2 trying...
    Producer3 made a product 0
    Consumer2 get a job Producer3 made a product 0
    Producer3 made a product 1
    Producer4 made a product 0
    Consumer5 trying...
    Consumer5 get a job Producer3 made a product 1
    Producer4 made a product 1
    Producer4 made a product 2
    Consumer3 trying...
    Producer2 made a product 0
    Consumer3 get a job Producer4 made a product 0
    Consumer1 trying...
    Producer5 made a product 0
    Consumer1 get a job Producer4 made a product 1
    Producer3 made a product 2
    Producer1 made a product 0
    Consumer4 trying...
    Consumer4 get a job Producer4 made a product 2
    Producer2 made a product 1
    Producer4 made a product 3
    Producer5 made a product 1

    可以看到,只有先生产出来,才能消费,否则阻塞等待。

  • 相关阅读:
    用sql合并列,两句话合为一句
    微信公众平台中添加qq在线聊天代码
    我被7岁4岁的小姐妹狠狠教训了一番
    Yahoo News Digest(雅虎新闻摘要)APP的推出,未来的seo界又要受伤了
    新浪微博@别人字母不分大小写(微博昵称不分大小写)
    最近打算体验一下discuz,有不错的结构化数据插件
    使用css3来实现边框圆角效果
    用WP_Query自定义WordPress 主循环
    关闭火车头dedecms发布模块自动关键词,解决火车头发布dedecms文章关键词过多问题
    dedecms发布文章时多个Tag间分割逗号自动变成英文逗号
  • 原文地址:https://www.cnblogs.com/DarrenChan/p/6534347.html
Copyright © 2020-2023  润新知