关于Java中阻塞队列BlockingQueue的详解

 更新时间:2023年05月19日 11:19:02   作者:书启秋枫  
这篇文章主要介绍了关于Java中阻塞队列BlockingQueue的详解,BlockingQueue是为了解决多线程中数据高效安全传输而提出的,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞,需要的朋友可以参考下

栈与队列概念

栈(Stack):先进后出,后进先出

队列:先进先出

1. 什么是BlockingQueue

在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤起。

BlockingQueue即阻塞队列,是java.util.concurrent下的一个接口,因此不难理解,BlockingQueue是为了解决多线程中数据高效安全传输而提出的。从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种:

  1. 当队列满了的时候进行入队列操作
  2. 当队列空了的时候进行出队列操作

因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空队列进行出队列操作时,它将会被阻塞,除非有另一个线程进行了入队列操作。

阻塞队列主要用在生产者/消费者的场景,下面这幅图展示了一个线程生产、一个线程消费的场景:

为什么需要BlockingQueue?

好处是我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给你一手包办了。在concurrent包发布以前,在多线程环境下,我们每个程序员都必须去自己控制这些细节,尤其还要兼顾效率和线程安全,而这会给我们的程序带来不小的复杂度。

2. 认识BlockingQueue

java.util.concurrent 包里的 BlockingQueue是一个接口,继承Queue接口,Queue接口继承 Collection。

BlockingQueue接口主要有以下7个实现类:

  1. ArrayBlockingQueue:由数组结构组成的有界阻塞队列。
  2. LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为integer.MAX_VALUE)阻塞队列。
  3. PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
  4. DelayQueue:使用优先级队列实现的延迟无界阻塞队列。
  5. SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列。
  6. LinkedTransferQueue:由链表组成的无界阻塞队列。
  7. LinkedBlockingDeque:由链表组成的双向阻塞队列。

BlockingQueue接口有以下几个方法:它的方法可以分成以下4类:

抛出异常特殊值阻塞超时
插入add(e)offer(e)put(e)offer(e, time, unit)
移除remove()poll()take()poll(time, unit)
检查element()peek()不可用不可用

① 抛出异常

add正常执行返回true,element(不删除)和remove返回阻塞队列中的第一个元素​ 当阻塞队列满时,再往队列里add插入元素会抛IllegalStateException:Queue full​ 当阻塞队列空时,再往队列里remove移除元素会抛NoSuchElementException​ 当阻塞队列空时,再调用element检查元素会抛出NoSuchElementException。

② 特定值

插入方法,成功ture失败false 移除方法,成功返回出队列的元素,队列里没有就返回null 检查方法,成功返回队列中的元素,没有返回null。

③ 一直阻塞

如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行。​ 当阻塞队列满时,再往队列里put元素,队列会一直阻塞生产者线程直到put数据or响应中断退出​ 当阻塞队列空时,再从队列里take元素,队列会一直阻塞消费者线程直到队列可用。

④ 超时退出

如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行,但等待时间不会超过给定值。​ 返回一个特定值以告知该操作是否成功(典型的是 true / false)。

3. 代码演示

public class BlockingQueueDemo {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
        // 第一组方法:add remove element
//        System.out.println(queue.add("a"));
//        System.out.println(queue.add("b"));
//        System.out.println(queue.add("c"));
//        // System.out.println(queue.add("d"));
//        // System.out.println(queue.element());
//        System.out.println(queue.remove());
//        System.out.println(queue.remove());
//        System.out.println(queue.remove());
//        //System.out.println(queue.remove());
//        //System.out.println(queue.element());
        // 第二组:offer poll peek
//        System.out.println(queue.offer("a"));
//        System.out.println(queue.offer("b"));
//        System.out.println(queue.offer("c"));
//        System.out.println(queue.offer("d"));
//        System.out.println(queue.peek());
//        System.out.println(queue.poll());
//        System.out.println(queue.poll());
//        System.out.println(queue.poll());
//        System.out.println(queue.poll());
//        System.out.println(queue.peek());
        // 第三组:put take
//        queue.put("a");
//        queue.put("b");
//        queue.put("c");
//        System.out.println(queue.take());
//        queue.put("d");
//        System.out.println(queue.take());
//        System.out.println(queue.take());
//        System.out.println(queue.take());
        // 第四组:offer poll
        System.out.println(queue.offer("a"));
        System.out.println(queue.offer("b"));
        System.out.println(queue.offer("c"));
        System.out.println(queue.offer("d", 5, TimeUnit.SECONDS));
    }
}

到此这篇关于关于Java中阻塞队列BlockingQueue的详解的文章就介绍到这了,更多相关Java阻塞队列BlockingQueue内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 教你利用springboot集成swagger并生成接口文档

    教你利用springboot集成swagger并生成接口文档

    有很多小伙伴不会利用springboot集成swagger并生成接口文档,今天特地整理了这篇文章,文中有非常详细的代码图文介绍及代码示例,对不会这个方法的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05
  • 与众不同的 Java 日期格式化大全

    与众不同的 Java 日期格式化大全

    这篇文章主要介绍了与众不同的 Java 日期格式化大全,在 Java 中,经常要将时间字符串转换为日期,或者要将日期转换为时间字符串。,需要的朋友可以参考下
    2019-06-06
  • java  使用URLDecoder和URLEncoder对中文进行处理

    java 使用URLDecoder和URLEncoder对中文进行处理

    这篇文章主要介绍了java 使用URLDecoder和URLEncoder对中文进行处理的相关资料,需要的朋友可以参考下
    2017-02-02
  • Springboot配置Swagger的实现示例

    Springboot配置Swagger的实现示例

    Swagger 是一种提高 API 开发和维护效率的工具,它使开发者能够更轻松地构建、测试和文档化 API,本文主要介绍了Springboot配置Swagger的实现示例,感兴趣的可以了解一下
    2023-10-10
  • Deep Module深模块之软件设计

    Deep Module深模块之软件设计

    这篇文章主要介绍了软件设计之Deep Module深模块详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • Java中反射的20个使用技巧分享

    Java中反射的20个使用技巧分享

    Java反射是一种强大的机制,允许程序在运行时检查和操作类,接口,字段和方法,本文总结了20个关于Java反射的经验,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-05-05
  • Java中bcrypt算法实现密码加密的方法步骤

    Java中bcrypt算法实现密码加密的方法步骤

    我们可以在Spring Boot和SSM中实现密码加密,使用bcrypt算法可以保障密码的安全性,并且减少了手动编写哈希函数的工作量,本文就来详细的介绍一下,感兴趣的可以了解一下
    2023-08-08
  • 你真的会使用Java的方法引用吗

    你真的会使用Java的方法引用吗

    这篇文章主要给大家介绍了关于Java方法引用的相关资料,方法引用是Java8的新特性,方法引用其实也离不开Lambda表达式,本文通过示例代码介绍的很详细,需要的朋友可以参考下
    2021-08-08
  • maven仓库repositories和mirrors的配置及区别详解

    maven仓库repositories和mirrors的配置及区别详解

    这篇文章主要介绍了maven仓库repositories和mirrors的配置及区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Java实现添加、验证PDF数字签名的方法示例

    Java实现添加、验证PDF数字签名的方法示例

    在设置文档内容保护的方法中,除了对文档加密、添加水印外,应用数字签名也是一种有效防伪手段。本文就使用Java实现添加、验证PDF数字签名,感兴趣的可以了解一下
    2021-07-07

最新评论