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一个知识点都能坚持用博客记录下来,加油!
  • 相关阅读:
    扫面线模板
    (动态规划、栈)leetcode 84. Largest Rectangle in Histogram, 85. Maximal Rectangle
    tmux 常见命令汇总
    leetcode 221
    leetcode 319 29
    (贪心)leetcode 392. Is Subsequence, 771. Jewels and Stones, 463. Island Perimeter
    leetcode 982 668
    Python import 同文件夹下的py文件的函数,pycharm报错
    Windows里Anaconda-Navigator无法打开的解决方案
    Windows下 gpu版 Tensorflow 安装
  • 原文地址:https://www.cnblogs.com/darling2047/p/15775903.html
Copyright © 2011-2022 走看看