zoukankan      html  css  js  c++  java
  • 【Java多线程】ArrayBlockingQueue阻塞队列原理分析(十六)

      阅读此篇文章请先了解

      AQS:【Java多线程】队列同步器AQS(十一)

      阻塞队列:【Java多线程】Java中的阻塞队列(十五)

    一、ArrayBlockingQueue介绍

      ArrayBlockingQueue是一个用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。

      类图结构如下:

      

    二、原理分析

    2.1 示例代码 

      设计目的:做个线程从阻塞队列中,获取元素或者放入元素,同一直接只有一个线程进行(获取或放入操作)。

      代码

      生产者Producer.java

     1 public class Producer implements Runnable {
     2     private BlockingQueue<Integer> numbersQueue;
     3 
     4     public Producer(BlockingQueue<Integer> numbersQueue) {
     5         this.numbersQueue = numbersQueue;
     6     }
     7     public void run() {
     8         try {
     9             while(true){
    10                 int num = ThreadLocalRandom.current().nextInt(100);
    11                 numbersQueue.put(num);
    12                 System.out.printf("%s:将%d号球放入队列中,存在%d个球
    ",Thread.currentThread().getName(), num, numbersQueue.size());
    13                 Thread.sleep(10);
    14             }
    15         } catch (InterruptedException e) {
    16             Thread.currentThread().interrupt();
    17         }
    18     }
    19 }

      消费者:Consumer.java

     1 public class Consumer implements Runnable {
     2 
     3     private BlockingQueue<Integer> numbersQueue;
     4 
     5 
     6 
     7     public Consumer(BlockingQueue<Integer> numbersQueue) {
     8         this.numbersQueue = numbersQueue;
     9     }
    10     public void run() {
    11         try {
    12             while(true){
    13 
    14 //                while (TestDemo.flag != 1) {
    15 //                    try {
    16 //                        Thread.sleep(1000);
    17 //                    } catch (InterruptedException e) {
    18 //                        e.printStackTrace();
    19 //                    }
    20 //                }
    21 
    22                 // 消费
    23                 Integer num = numbersQueue.take();
    24                 System.out.printf("%s:将%d号球从队列中取出,队列中还存在%d个球
    ", Thread.currentThread().getName() ,num, numbersQueue.size());
    25 
    26                 Thread.sleep(10);
    27 
    28             }
    29         } catch (InterruptedException e) {
    30             Thread.currentThread().interrupt();
    31         }
    32     }
    33 }

      测试TestDemo.java

     1 public class TestDemo {
     2 
     3     public static volatile int flag = 0;
     4 
     5     public static void main(String[] args) {
     6 
     7         int BOUND = 10;
     8         int N_PRODUCERS = 10;
     9         int N_CONSUMERS = 10;
    10 
    11         BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(BOUND);
    12 
    13         for (int i = 0; i < N_PRODUCERS; i++) {
    14             new Thread(new Producer(queue), "生产者" + i).start();
    15         }
    16 
    17         for (int j = 0; j < N_CONSUMERS; j++) {
    18             new Thread(new Consumer(queue), "消费者" + j).start();
    19         }
    20 
    21 
    22         // 控制消费者
    23         // 输入不等于1 继续等待
    24         Scanner scanner = new Scanner(System.in);
    25         while (true) {
    26             try {
    27                 flag = scanner.nextInt();
    28                 Thread.sleep(1000);
    29             } catch (InterruptedException e) {
    30                 e.printStackTrace();
    31             }
    32         }
    33     }
    34 
    35 }

    2.1 原理图 

      1、put(e) 与 take() 流程图

      

      2、阻塞队列状态图

      

      

      

  • 相关阅读:
    Erlang 杂记 IV
    ASP.NET MVC的View是如何被呈现出来的?[设计篇]
    面向对象—在线文件管理模块
    软件开发中个人在团队里的效绩评定
    用go语言遍历文件夹
    磁盘缓存的算法:写算法
    一种Lua到C的封装
    从信息系统界面设计引发的思考
    基于Backbone.js的JavaScript MVC示例程序
    C和C++
  • 原文地址:https://www.cnblogs.com/h--d/p/14563163.html
Copyright © 2011-2022 走看看