java 中 阻塞隊列BlockingQueue詳解及實例
BlockingQueue很好的解決了多線程中數據的傳輸,首先BlockingQueue是一個接口,它大致有四個實現類,這是一個很特殊的隊列,如果BlockQueue是空的,從BlockingQueue取東西的操作將會被阻斷進入等待狀態,直到BlockingQueue進了東西才會被喚醒.同樣,如果BlockingQueue是滿的,任何試圖往里存東西的操作也會被阻斷進入等待狀態,直到BlockingQueue里有空間才會被喚醒繼續操作。
BlockingQueue的四個實現類:
1.ArrayBlockingQueue:規定大小的BlockingQueue,其構造函數必須帶一個int參數來指明其大小.其所含的對象是以FIFO(先入先出)順序排序的.
2.LinkedBlockingQueue:大小不定的BlockingQueue,若其構造函數帶一個規定大小的參數,生成的BlockingQueue有大小限制,若不帶大小參數,所生成的BlockingQueue的大小由Integer.MAX_VALUE來決定.其所含的對象是以FIFO(先入先出)順序排序的
3.PriorityBlockingQueue:類似于LinkedBlockQueue,但其所含對象的排序不是FIFO,而是依據對象的自然排序順序或者是構造函數的Comparator決定的順序.
4.SynchronousQueue:特殊的BlockingQueue,對其的操作必須是放和取交替完成的.
BlockingQueue的常用方法:
1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容納,則返回true,否則報異常
2)offer(anObject):表示如果可能的話,將anObject加到BlockingQueue里,即如果BlockingQueue可以容納,則返回true,否則返回false.
3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue沒有空間,則調用此方法的線程被阻斷直到BlockingQueue里面有空間再繼續.
4)poll(time):取走BlockingQueue里排在首位的對象,若不能立即取出,則可以等time參數規定的時間,取不到時返回null
5)take():取走BlockingQueue里排在首位的對象,若BlockingQueue為空,阻斷進入等待狀態直到Blocking有新的對象被加入為止
例子:
這個例子主要模擬了生產者和消費者之間的工作流程,是一個簡單的消費者等待生產者生產產品供消費者消費的場景。
生產者:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.gefufeng; import java.util.concurrent.BlockingQueue; public class Producter implements Runnable{ private BlockingQueue<String> blockingQueue; public Producter(BlockingQueue<String> blockingQueue){ this .blockingQueue = blockingQueue; } @Override public void run() { try { blockingQueue.put( "我生產的" + Thread.currentThread().getName()); System.out.println( "我生產的" + Thread.currentThread().getName()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println( "生產失敗" ); } } } |
消費者:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package com.gefufeng; import java.util.concurrent.BlockingQueue; public class Customer implements Runnable{ private BlockingQueue<String> blockingQueue; public Customer(BlockingQueue<String> blockingQueue){ this .blockingQueue = blockingQueue; } @Override public void run() { for (;;){ try { String threadName = blockingQueue.take(); System.out.println( "取出:" + threadName); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println( "取出失敗" ); } } } } |
執行類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package com.gefufeng; import java.util.concurrent.ArrayBlockingQueue; public class Executer { public static void main(String[] args) { ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<String>( 2 ); Producter producter = new Producter(arrayBlockingQueue); Customer cusotmer = new Customer(arrayBlockingQueue); new Thread(cusotmer).start(); for (;;){ try { Thread.sleep( 2000 ); new Thread(producter).start(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } |
首先是消費者循環等待產品,當第一次循環時執行blockingQueue.take(),是拿不出任何產品的,于是進入阻塞狀態,兩秒后,生產者生產了一個產品,于是blockingQueue拿到產品,打印了日志,然后消費者執行第二次循環,發現blockingQueue.take()又沒拿到產品,于是又進入阻塞狀態。。。依次循環
感謝閱讀,希望能幫助到大家,謝謝大家,對本站的支持!
原文鏈接:https://my.oschina.net/gef/blog/825029