H__D  

  阅读此篇文章请先了解

  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个球\n",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个球\n", 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、阻塞队列状态图

  

  

  

 

posted on 2021-03-21 16:03  H__D  阅读(164)  评论(0编辑  收藏  举报