JUC并发编程——BlockingQueue阻塞队列的使用

·  阅读 81

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

1、BlockingQueue 简介

BlockingQueue:阻塞队列,遵循FIFIO(先进先出)

BlockingQueue 提供了线程安全的队列访问方式:当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满;从阻塞队列取数据时,如果队列已空,线程将会阻塞等待直到队列非空。

多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享。生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。

2、BlockingQueue 继承关系

BlockingQueue是 java.util.concurrent 包里的一个接口, 继承Queue接口,Queue接口继承 Collection,Set 和 List 也继承与Collection,BlockingQueue 继承关系如下图:

在这里插入图片描述

Deque:双端队列,是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。

LinkedBlockingQueue 是一个基于链表实现的可选容量的阻塞队列。如果在初始化时没有指定容量,那么默认使用int的最大值作为队列容量。队头的元素是插入时间最长的,队尾的元素是最新插入的。新的元素将会被插入到队列的尾部。

ArrayBlockingQueue 底层是使用一个数组实现队列的,并且在构造ArrayBlockingQueue时需要指定容量,也就意味着底层数组一旦创建了,容量就不能改变了,因此ArrayBlockingQueue是一个容量限制的阻塞队列。因此,在队列全满时执行入队将会阻塞,在队列为空时出队同样将会阻塞。

3、BlockingQueue 四组API

1、抛出异常

    public static void test1(){
        //创建一个大小为3的数组阻塞队列
        ArrayBlockingQueue<Object> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
        //添加元素
        System.out.println(arrayBlockingQueue.add("a"));//true
        System.out.println(arrayBlockingQueue.add("b"));
        System.out.println(arrayBlockingQueue.add("c"));
//      System.out.println(arrayBlockingQueue.add("d"));//添加失败,抛出异常 Queue full

        System.out.println(arrayBlockingQueue.element());//取出队首元素

        //取出元素
        System.out.println(arrayBlockingQueue.remove());
        System.out.println(arrayBlockingQueue.remove());
        System.out.println(arrayBlockingQueue.remove());
    }
复制代码

2、不抛异常,有返回值

public static void test2(){
    //创建一个大小为3的数组阻塞队列
    ArrayBlockingQueue<Object> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
    //添加元素
    System.out.println(arrayBlockingQueue.offer("a"));//true
    System.out.println(arrayBlockingQueue.offer("b"));
    System.out.println(arrayBlockingQueue.offer("c"));
    System.out.println(arrayBlockingQueue.offer("d"));//添加失败,返回false

    System.out.println(arrayBlockingQueue.peek());//取出队首元素

    //取出元素
    System.out.println(arrayBlockingQueue.poll());
    System.out.println(arrayBlockingQueue.poll());
    System.out.println(arrayBlockingQueue.poll());
}
复制代码

3、一直等待

    public static void test3() throws InterruptedException {
        //创建一个大小为3的数组阻塞队列
        ArrayBlockingQueue<Object> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
        //添加元素
        arrayBlockingQueue.put("a");//true
        arrayBlockingQueue.put("b");
        arrayBlockingQueue.put("c");
        arrayBlockingQueue.put("d");//添加失败,程序会一直等待


        //取出元素
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
    }
复制代码

4、超时等待

public static void test4() throws InterruptedException {
    //创建一个大小为3的数组阻塞队列
    ArrayBlockingQueue<Object> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
    //添加元素
    System.out.println(arrayBlockingQueue.offer("a"));//true
    System.out.println(arrayBlockingQueue.offer("b"));
    System.out.println(arrayBlockingQueue.offer("c"));
    System.out.println(arrayBlockingQueue.offer("d",3, TimeUnit.SECONDS));//等待3秒钟,如果添加失败,返回false,程序结束

    System.out.println(arrayBlockingQueue.peek());//取出队首元素

    //取出元素
    System.out.println(arrayBlockingQueue.poll());
    System.out.println(arrayBlockingQueue.poll());
    System.out.println(arrayBlockingQueue.poll());
    System.out.println(arrayBlockingQueue.poll(3, TimeUnit.SECONDS));//等待3秒钟,如果取出失败,返回null,程序结束
}
复制代码

四组API总结:

方式抛出异常不抛异常,有返回值一直等待超时等待
添加add()offer()put()offer(E e, long timeout, TimeUnit unit)
移除remove()poll()take()poll(long timeout, TimeUnit unit)
查看队首元素element()peek()
分类:
后端
标签: