zoukankan      html  css  js  c++  java
  • BlockingQueue家族成员一览

          最近在复习多线程的知识,必然少不了要扫描一遍JUC包下的各个类或接口,今天就先来聊一聊阻塞队列BlockingQueue;

          BlockingQueue是jdk1.5发布的JUC包下的一个工具类,他提供了天生阻塞的拿(put)和取(take)元素的方法,线程安全,通过其阻塞的put、take方法能很好的实现生产者消费者模型,解决线程间的通信问题,

          下面先分别介绍其本身拥有的一些特性方法和实现类

          特性方法

          boolean add(E e);        添加元素,成功返回true,失败返回false,如果队列设置了长度,超长会抛java.lang.IllegalStateException: Queue full异常

          void put(E e);               阻塞式的添加元素,如果队列超长当前线程会一直阻塞,直到队列里的元素被take可以成功添加为止

          boolean offer(E e);       添加元素,成功返回true,失败返回false,与add的区别在于队列满了添加失败不会抛异常而是返回false

          E take();                        阻塞式的获取队列元素,只要take不到元素当前线程会一直阻塞,直到队列里有元素并成功获取

          E poll();                        从队列头部获取并移除元素,获取不到返回null

          E peek();                      从队列头部获取元素但不移除元素,获取不到返回null

         int drainTo(Collection<? super E> c);   将队列中的元素全部移除,并发送到给定的集合中,返回的是操作成功的元素个数

         特性方法对应的测试用例

    /**
     * @description: 阻塞队列的常用方法测试
     * @author: dll
     * @date: Created in 2022/1/6 14:47
     * @version:
     * @modified By:
     */
    public class T08_TestBlockingQueue {
    
        public static void main(String[] args) throws InterruptedException {
            testDrainTo();
        }
    
        /**
         * 将队列中的元素全部移除,并发送到给定的集合中。
         */
        private static void testDrainTo () {
            BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
            queue.add("1");
            queue.add("3");
            ArrayList list = new ArrayList();
            System.out.println("queue.peek() = " + queue.peek());
            int i = queue.drainTo(list);
            System.out.println("i = " + i);
            System.out.println("list.toString() = " + list.toString());
            System.out.println("queue.peek() = " + queue.peek());
        }
    
        /**
         * 从队列头部获取并移除元素,获取不到为null
         */
        private static void testPoll() {
            BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
            queue.add("123");
            System.out.println("queue.poll(1) = " + queue.poll());
            System.out.println("queue.remainingCapacity() = " + queue.remainingCapacity());
            System.out.println("queue.poll(2) = " + queue.poll());
        }
    
        /**
         * 阻塞式的获取队列元素,只要take不到元素当前线程会一直阻塞,直到队列里有元素并成功获取
         */
        private static void testTake() throws InterruptedException {
            BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(5);
                    queue.add("456");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            queue.put("123");
            System.out.println("queue.take() = " + queue.take());
            // 此处会阻塞住,直到上面的线程唤醒后往队列添加了元素
            System.out.println("queue.take() = " + queue.take());
        }
    
        /**
         * 添加元素,成功返回true,失败返回false,如果队列设置了长度,超长会抛java.lang.IllegalStateException: Queue full异常
         * 参数不能为null
         */
        private static void testAdd() {
            BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
            System.out.println("queue.offer() = " + queue.add("123"));
            System.out.println("queue.offer() = " + queue.add("123"));
        }
    
        /**
         * 添加元素,成功返回true,失败返回false,与add的区别在于队列满了添加失败不会抛异常而是返回false
         * 参数不能为null
         */
        private static void testOffer() {
            BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
            System.out.println("queue.offer() = " + queue.offer("123"));
            System.out.println("queue.offer() = " + queue.offer("123"));
        }
    
        /**
         * 测试put方法的阻塞式添加
         * 阻塞式的添加元素,如果队列超长当前线程会一直阻塞,直到队列里的元素被take可以成功添加为止
         * 参数不能为null
         * @throws InterruptedException
         */
        private static void testPut() throws InterruptedException {
            BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(5);
                    // 此处用peek下面的put方法仍会阻塞,因为peek只是拿出元素并不会将元素从队列移除
                    System.out.println("线程里获取到的元素:" + queue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            System.out.println("queue.add() = " + queue.add("1"));
            // 此处调用会阻塞当前线程,直至上面的线程被唤醒从队列里拿走一个元素
            queue.put("12");
            System.out.println("主线程里take的元素:" + queue.take());
        }
    
    }

         关于实现类我也不想利用文本的方式一个个列起来了,下面直接附上我整理的思维导图的部分截图,简单明了:

                需要注意的是,BlockingQueue的一众实现类是线程池接收任务队列的多种实现,不同的队列应用于不同场景下的线程池;后面会抽时间写一篇关于线程池的总结笔记

             

    希望每get一个知识点都能坚持用博客记录下来,加油!
  • 相关阅读:
    springboot整合shiro
    四大作用域:application,session,request,page
    Application作用域实现:当用户重复登录时,挤掉原来的用户
    从Linux下载大于4G文件到本地,并且在本地合并
    idea+maven+springboot+mybatis
    Spring 3.0 中一般 普通类调用service
    java微信扫码支付Native(模式二)
    阿里云不支持stmp 的25端口,必须
    python写入文本报错TypeError: expected a string or other character buffer object
    mysql找到数据的存储位置
  • 原文地址:https://www.cnblogs.com/darling2047/p/15775903.html
Copyright © 2011-2022 走看看