見賢思齊焉,見不賢而內自省也。—《論語》
PS: 如果覺得本文有用的話,請幫忙點贊,留言評論支持一下哦,您的支持是我最大的動力!謝謝啦~
Java5.0 增加了兩種新的容器類型,它們是指:Queue 和 BlockingQueue。Queue 用來臨時保存一組等待處理的元素。BlockingQueue 擴張了 Queue 接口,增加了可阻塞的插入和獲取等操作。
BlockingQueue 通常運用於一個線程生產對象放入隊列,另一個線程從隊列獲取對象並消費,這是典型的生產者消費者模型。
這裏寫圖片描述
生產者線程持續生產新對象並插入隊列,如果隊列已滿,那麼插入對象的操作會一直阻塞,直到隊列中出現可用的空間。
消費者線程持續從隊列獲取對象,如果隊列爲空,那麼獲取操作會一直阻塞,直到隊列中出現可用的新對象。BlockingQueue 簡化了生產者-消費者設計的實現過程,它支持任意數量的生產者和消費者。
BlockingQueue 的核心方法:
這裏寫圖片描述
offer(E): 向隊列插入元素,並返回插入成功與否。本方法不阻塞當前執行線程。
put(E) : 向隊列插入元素,如果隊列已滿,則會阻塞當前線程直至元素加入隊列。
take() : 獲取隊列的首位元素,如果隊列爲空,則阻塞當前線程直至隊列有元素並取走。
poll():獲取隊列首個元素,指定時間內一旦數據可取,則立即返回;否則返回失敗。
remove(E):刪除隊列中的元素,返回成功與否。
BlockingQueue 的實現
BlockingQueue是一個接口,所以你必須使用它的實現來使用它。它的實現包括以下幾個:
ArrayBlockingQueue:基於數組實現的有界隊列(FIFO),使用一把全局鎖並行對 queue 讀寫操作,同時使用兩個 Condition 阻塞隊列爲空時的取操作和隊列爲滿時的寫操作。
LinkedBlockingQueue:基於已鏈接節點的,範圍上限爲 Integer.MAX_VALUE 的 blocking queue(FIFO)。主要操作 put 和 take 都是阻塞的。
DelayQueue:當指定的延遲時間到了,才能夠從隊列中獲取元素。它沒有大小限制,因此插入元素時不會阻塞,而只有獲取元素時纔會被阻塞。它的用法可以參考下面兩篇博客:
http://www.cnblogs.com/jobs/archive/2007/04/27/730255.html,
http://www.cnblogs.com/sunzhenchao/p/3515085.htmlPriorityBlockingQueue: 基於優先級的阻塞隊列,但需要注意的是PriorityBlockingQueue並不會阻塞數據生產者,而只會在沒有可消費的數據時,阻塞數據的消費者。
SynchronoutQueue:它的內部同時只能夠容納單個元素。如果該隊列已有一個元素的話,試圖向隊列插入一個新元素線程會阻塞,知道另一個線程將該元素從隊列中拿走。同樣,如果該隊列爲空,試圖向隊列中抽取一個元素的線程將會阻塞,知道另一個線程向隊列中插入一個新的元素。SynchronousQueue適合一對一的匹配場景,沒有容量,無法緩存。它的用法強烈推薦博客:
http://www.cnblogs.com/leesf456/p/5560362.html
BlockingQueue的使用
這是一個使用 BlockingQueue 的例子,本例使用 ArrayBlockingQueue 實現。首先,BlockingQueueTest 創建一個生產者線程 Procucer, 把字符存放進共享隊列。然後創建三個消費者線程 Consumer,把字符串從隊列中取出。Consumer 取到最後一個字符串時,中斷所有消費者線程,結束程序。
1import java.util.ArrayList;
2import java.util.Iterator;
3import java.util.List;
4import java.util.Vector;
5import java.util.concurrent.ArrayBlockingQueue;
6import java.util.concurrent.BlockingQueue;
7
8public class BlockingQueueTest {
9 //隊列容量
10 private static final int SIZE = 5;
11 private static final int CONSUMER_SIZE = 3;
12 //消費者線程退出標誌
13 private static String endString = "num:" + (SIZE*2-1);
14 //存放消費者線程
15 private static List list = new ArrayList<Thread>();
16
17 public static void main(String[] args) throws Exception{
18 //創建固定長度的阻塞隊列
19 BlockingQueue q = new ArrayBlockingQueue<String>(SIZE);
20
21 //創建生產者
22 Producer producer = new Producer(q);
23 //啓動生產者線程,生產對象
24 producer.start();
25
26 //啓動消費者線程,獲取隊列對象
27 for(int i = 0; i < CONSUMER_SIZE; i++) {
28 list.add(new Consumer(q));
29 ((Thread) list.get(i)).start();
30 }
31 }
32
33 //中斷線程
34 public static void shutDownThread() {
35 for(int i = 0; i < CONSUMER_SIZE; i++) {
36 ((Thread) list.get(i)).interrupt();
37 }
38 }
39
40 static class Producer extends Thread{
41
42 private BlockingQueue queue = null;
43
44 public Producer(BlockingQueue q) {
45 this.queue = q;
46 }
47
48 @Override
49 public void run() {
50 // TODO Auto-generated method stub
51 try {
52 //生產10個對象,放進隊列
53 for(int i = 0; i < SIZE*2; i++) {
54 String str = "num:" + i;
55 System.out.println(Thread.currentThread().getName() +":"+"IN: " + str);
56 queue.put(str);
57 Thread.sleep(100);
58 }
59 } catch (InterruptedException e) {
60 // TODO Auto-generated catch block
61 e.printStackTrace();
62 }
63
64 }
65 }
66
67 //消費者線程
68 static class Consumer extends Thread{
69
70 private BlockingQueue queue = null;
71
72 public Consumer(BlockingQueue q) {
73 this.queue = q;
74 }
75
76 @Override
77 public void run() {
78 // TODO Auto-generated method stub
79 try {
80 //獲取隊列的元素,隊列爲空時會阻塞
81 while(true) {
82 String str = (String) queue.take();
83 System.out.println(Thread.currentThread().getName() + ":" + "OUT " + str);
84 //已經取出最後一個元素,消費者線程應該退出,否則程序一直在運行
85 if(str.equals(endString)) {
86 shutDownThread();//中斷線程
87 }
88 }
89 } catch (InterruptedException e) {
90 // TODO Auto-generated catch block
91 e.printStackTrace();
92 }
93 }
94 }
95}
執行結果:
這裏寫圖片描述
總結
java.util.concurrent 中實現的阻塞隊列包含了足夠的同步機制,從而能夠安全的將對象從生產者線程發佈到消費者線程。對於可變對象,生產者-消費者模型,把對象的所有權安全的從生產者交付給消費者。轉移後,消費者線程獲得這個對象的所有權(獨佔訪問權,可以任意修改它),並且生產者線程不會再訪問它。同時,阻塞隊列負責所有的控制流,使得消費者生產者的代碼更加簡單和清晰。
本文完畢,如對你有幫助,請關注我,謝謝~
參考
https://blog.csdn.net/defonds/article/details/44021605/
http://www.cnblogs.com/leesf456/p/5428630.html
《併發編程實戰》