java.util.concurrent包中的Java BlockingQueue接口表示一個(gè)線程安全的隊(duì)列碰凶,可以放入并獲取實(shí)例边翼。
在這篇文章中疮蹦,我會(huì)告訴你如何使用這個(gè)BlockingQueue姿锭。
本文將不討論如何在Java中實(shí)現(xiàn)BlockingQueue。如果您對此感興趣壹粟,在我的偏理論的Java并發(fā)教程中有一個(gè)關(guān)于阻塞隊(duì)列的文章。
BlockingQueue 使用
BlockingQueue通常用于使線程產(chǎn)生對象宿百,而另一線程則使用該對象趁仙。這是一張闡明這一原理的圖表。
生產(chǎn)線程將持續(xù)生產(chǎn)新對象并將它們插入隊(duì)列雀费,直到隊(duì)列達(dá)到它可以包含的上限。換句話說痊焊,這是極限盏袄。如果阻塞隊(duì)列達(dá)到其上限,則會(huì)在嘗試插入新對象時(shí)阻塞生產(chǎn)線程薄啥。在消耗線程將對象帶出隊(duì)列之前辕羽,它一直處于阻塞狀態(tài)。
消費(fèi)線程不斷將對象從阻塞隊(duì)列中取出垄惧,并對其進(jìn)行處理刁愿。如果消費(fèi)線程試圖將對象從空隊(duì)列中取出,則消費(fèi)線程將被阻塞到逊,直到生成的線程將對象放入隊(duì)列铣口。
BlockingQueue 方法
BlockingQueue有4種不同的方法來插入、刪除和檢查隊(duì)列中的元素觉壶。每一組方法的行為都是不同的脑题,以防被請求的操作不能立即執(zhí)行。下面是這些方法的一個(gè)表:
Throws Exception | 特殊值 | 阻塞 | 超時(shí) | |
---|---|---|---|---|
Insert | add(o) | offer(o) | put(o) | offer(o, timeout, timeunit) |
Remove | remove(o) | poll() | take() | poll(timeout, timeunit) |
Examine | element() | peek() |
這四種不同的行為方式意思
- Throws Exception: 如果嘗試的操作不可能立即發(fā)生铜靶,則拋出一個(gè)異常叔遂。
- 特殊值:如果嘗試的操作不能立即執(zhí)行,則會(huì)返回一個(gè)特殊值(通常為true / false)。
- 阻塞:如果嘗試的操作不可能立即執(zhí)行掏熬,那么該方法將阻塞佑稠。
- 超時(shí):如果嘗試的操作不可能立即執(zhí)行,則該方法調(diào)用將阻塞旗芬,但不會(huì)超過給定的超時(shí)舌胶。
返回一個(gè)特殊值,告訴操作是否成功(通常為true / false)疮丛。
無法將null插入到BlockingQueue中幔嫂。如果嘗試插入null,則BlockingQueue將引發(fā)NullPointerException誊薄。
也可以訪問BlockingQueue中的所有元素履恩,而不僅僅是開始和結(jié)束處的元素。例如呢蔫,假設(shè)你需要處理隊(duì)列中的一個(gè)對象切心,但你的應(yīng)用程序決定不處理它。然后你可以調(diào)用remove(o)刪除隊(duì)列中的特定對象片吊。但是绽昏,這并不是非常有效,所以除非你真的需要俏脊,否則不應(yīng)該使用這些Collection方法
BlockingQueue 實(shí)現(xiàn)
由于BlockingQueue是一個(gè)接口全谤,因此您需要使用它的一個(gè)實(shí)現(xiàn)來使用它。java.util.concurrent包具有以下BlockingQueue接口(在Java 6中)的實(shí)現(xiàn):
BlockingQueue 例子
這是一個(gè)Java BlockingQueue示例爷贫。該示例使用BlockingQueue接口的ArrayBlockingQueue實(shí)現(xiàn)认然。
首先,BlockingQueueExample類在不同的線程中啟動(dòng)生產(chǎn)者和消費(fèi)者漫萄。生產(chǎn)者將字符串插入共享BlockingQueue中卷员,消費(fèi)者將它們?nèi)〕觥?/p>
public class BlockingQueueExample {
public static void main(String[] args) throws Exception {
BlockingQueue queue = new ArrayBlockingQueue(1024);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
new Thread(producer).start();
new Thread(consumer).start();
Thread.sleep(4000);
}
}
這是生產(chǎn)者類。注意它在每個(gè)put()調(diào)用之間的使用sleep腾务。這將導(dǎo)致消費(fèi)者在等待隊(duì)列中的對象時(shí)阻塞子刮。
public class Producer implements Runnable{
protected BlockingQueue queue = null;
public Producer(BlockingQueue queue) {
this.queue = queue;
}
public void run() {
try {
queue.put("1");
Thread.sleep(1000);
queue.put("2");
Thread.sleep(1000);
queue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
這是消費(fèi)者類。
它只是從隊(duì)列中取出對象窑睁,并將它們打印到System.out挺峡。
public class Consumer implements Runnable{
protected BlockingQueue queue = null;
public Consumer(BlockingQueue queue) {
this.queue = queue;
}
public void run() {
try {
System.out.println(queue.take());
System.out.println(queue.take());
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
[原文](http://tutorials.jenkov.com/java-util-concurrent/blockingqueue.html)