• Java:阻塞队列BlockingQueue与应用场景


    目录

    阻塞队列

    BlockingQueue的常用方法

     生产者消费者应用场景


    阻塞队列

            阻塞队列BlockingQueue继承自父类Queue,该队列是线程安全的,可以安全的与多个生产者和消费者线程一起使用。

            与阻塞队列相对的,存在“非阻塞队列”的概念,那么两者在入队和出队时的区别是什么呢?答案如下图所示,

             此外,在jdk1.8的源码中,对BlockingQueue的文档注释信息与简单翻译如下,

        A {@link java.util.Queue} that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
        阻塞队列,当获取元素时,会等待队列变为非空状态,才会返回元素值;当写入元素时,会等待队列变为非满状态时,再将其写入。

            核心思想如下:

                    ①阻塞队列在变为空时,继续执行取出队列元素的操作时,会发生阻塞,直到队列中有新的元素被写入时,才停止阻塞,取出元素;

                    ②阻塞队列在已满时,继续执行写入元素的操作时,会发生阻塞,直到队列中已有的元素被消费而产生空位时,才停止阻塞,写入元素。

    BlockingQueue的常用方法

                    BlockingQueue提供了如下的常用方法,但是请注意:并非所有的方法都会产生队列阻塞的效果。

                     其中:阻塞的方法是:put()-添加take()-取出

     生产者消费者应用场景

            阻塞队列的一个经典应用场景就是:生产者、消费者问题

            如下示例代码中,基于BlockingQueue阻塞队列与子类ArrayBlockingQueue有限阻塞队列,分别创建了2个生产者线程、1个消费者线程。2个生产者线程每隔2秒生产一个随机数,供这1个消费者进行消费。

    1. import java.util.Random;
    2. import java.util.concurrent.ArrayBlockingQueue;
    3. import java.util.concurrent.BlockingQueue;
    4. //生产者
    5. class Producer implements Runnable{
    6. private final BlockingQueue blockingQueue;//阻塞队列
    7. private final Random random = new Random();//随机数生成器
    8. //构造器
    9. public Producer(BlockingQueue queue){
    10. this.blockingQueue = queue;//初始化阻塞队列
    11. }
    12. //线程任务
    13. @Override
    14. public void run() {
    15. while (true){
    16. //添加产品到阻塞队列
    17. try {
    18. Thread.sleep(2000);//每隔2秒执行一次生产任务
    19. System.out.println("生产者产出产品");
    20. this.blockingQueue.put(this.produce());
    21. } catch (InterruptedException e) {
    22. e.printStackTrace();
    23. System.out.println("生产时发生异常");
    24. }
    25. }
    26. }
    27. //生产方法-生产随机数
    28. Object produce(){
    29. return random.nextInt();
    30. }
    31. }
    32. //消费者
    33. class Consumer implements Runnable{
    34. //阻塞队列
    35. private final BlockingQueue blockingQueue;
    36. //构造器
    37. public Consumer(BlockingQueue queue){
    38. this.blockingQueue = queue;
    39. }
    40. //执行线程任务
    41. @Override
    42. public void run() {
    43. while (true){
    44. try {
    45. this.consume(this.blockingQueue.take());
    46. } catch (InterruptedException e) {
    47. e.printStackTrace();
    48. System.out.println("消费时发生异常");
    49. }
    50. }
    51. }
    52. //消费方法
    53. public void consume(Object production){
    54. System.out.println("正在消费产品:"+production);
    55. }
    56. }
    57. public class BlockingQueue_Apply {
    58. //properties
    59. //methods
    60. public static void main(String[] args) {
    61. //创建阻塞队列ArrayBlockingQueue-指定容量为10
    62. ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(10);
    63. //创建生产者-2个生产商
    64. Producer producer = new Producer(blockingQueue);
    65. Producer producer1 = new Producer(blockingQueue);
    66. //创建消费者
    67. Consumer consumer = new Consumer(blockingQueue);
    68. //生产者线程
    69. Thread producerThread = new Thread(producer);
    70. Thread producerThread1 = new Thread(producer1);
    71. //消费者线程
    72. Thread consumerThread = new Thread(consumer);
    73. //启动线程任务
    74. producerThread.start();
    75. producerThread1.start();
    76. consumerThread.start();
    77. }
    78. }

                     如上图所示,该案例中,会不断执行发生生产者生产、消费者消费的子线程任务,并打印信息。

  • 相关阅读:
    C语言:位段、枚举、联合体
    JZ18 删除链表的节点
    华为李鹏:到 2025 年智能算力需求将达到目前水平的 100 倍
    3、AWS SDK for Go使用
    Oracle VM VirtualBox安装CentOS 7系统
    【JAVA学习笔记】67 - 坦克大战1.5 - 1.6,防止重叠,记录成绩,选择是否开新游戏或上局游戏,播放游戏音乐
    数学建模 线性规划 遗传算法
    Python中的异常处理3-2
    Kotlin 1.5新特性记录
    模仿Spring注入接口的代理类全过程
  • 原文地址:https://blog.csdn.net/weixin_43524214/article/details/127975036