從J2SE 5.0開(kāi)始有了java.util.concurrent套件,其中的類(lèi)可以使實(shí)現(xiàn)多線(xiàn)程相關(guān)功能更為方便。本節(jié)將簡(jiǎn)介concurrent套件中的幾個(gè)簡(jiǎn)單常用的類(lèi)。
15.3.1 BlockingQueue
隊(duì)列(Queue)是一個(gè)先進(jìn)先出(First In First Out, FIFO)的數(shù)據(jù)結(jié)構(gòu)。在J2SE 5.0中增加了java.util.concurrent.BlockingQueue。在多線(xiàn)程情況下,如果BlockingQueue的內(nèi)容為空,而有個(gè)線(xiàn)程試圖從Queue中取出元素,則該線(xiàn)程會(huì)被Block,直到Queue有元素時(shí)才解除Block;反過(guò)來(lái),如果 BlockingQueue滿(mǎn)了,而有個(gè)線(xiàn)程試圖再把數(shù)據(jù)填入Queue中,則該線(xiàn)程會(huì)被Block,直到Queue中有元素被取走后解除Block。
BlockingQueue的幾個(gè)主要操作如表15-1所示。
表15-1 BlockingQueue的幾個(gè)操作
![]() |
java.util.concurrent中提供幾種不同的BlockingQueue。ArrayBlockingQueue要指定容量大小來(lái)構(gòu)建。LinkedBlockingQueue默認(rèn)沒(méi)有容量上限,但也可以指定容量上限。PriorityBlockingQueue嚴(yán)格來(lái)說(shuō)不是Queue,因?yàn)樗歉鶕?jù)優(yōu)先權(quán)(Priority)來(lái)移除元素。
我們以在wait()、notify()介紹時(shí)的生產(chǎn)者、消費(fèi)者程序?yàn)槔褂肂lockQueue來(lái)加以改寫(xiě),優(yōu)點(diǎn)是不用親自處理wait()、notify()的細(xì)節(jié)。首先生產(chǎn)者改寫(xiě)如范例15.21所示:
范例15.21 ProducerQueue.java
package onlyfun.caterpillar; import java.util.concurrent.BlockingQueue; public class ProducerQueue implements Runnable { private BlockingQueue<Integer> queue; public ProducerQueue(BlockingQueue<Integer> queue) { this.queue = queue; } public void run() { for(int product = 1; product <= 10; product++) { try { // wait for a random time Thread.sleep((int) Math.random() * 3000); queue.put(product); } catch(InterruptedException e) { e.printStackTrace(); } } } } |
可以看到,直接使用BlockingQueue,會(huì)自動(dòng)處理同步化、wait()和notify()的執(zhí)行。消費(fèi)者類(lèi)改寫(xiě)如范例15.22所示:
范例15.22 ConsumerQueue.java
package onlyfun.caterpillar; import java.util.concurrent.BlockingQueue; public class ConsumerQueue implements Runnable { private BlockingQueue<Integer> queue; public ConsumerQueue(BlockingQueue<Integer> queue) { this.queue = queue; } public void run() { for(int i = 1; i <= 10; i++) { try { // wait for a random time Thread.sleep((int) (Math.random() * 3000)); queue.take(); } catch(InterruptedException e) { e.printStackTrace(); } } } } |
可以使用范例15.23進(jìn)行簡(jiǎn)單的測(cè)試:
范例15.23 BlockingQueueDemo.java
package onlyfun.caterpillar; import java.util.concurrent.BlockingQueue; public class ConsumerQueue implements Runnable { private BlockingQueue<Integer> queue; public ConsumerQueue(BlockingQueue<Integer> queue) { this.queue = queue; } public void run() { for(int i = 1; i <= 10; i++) { try { // 等待一個(gè)隨機(jī)時(shí)間 Thread.sleep((int) (Math.random() * 3000)); queue.take(); } catch(InterruptedException e) { e.printStackTrace(); } } } } |
由于BlockingQueue不需要您來(lái)控制,所以沒(méi)有特意顯示信息以表示生產(chǎn)者、消費(fèi)者放入產(chǎn)品至Queue的信息,不過(guò)仍可以在ProducerQueue與ConsumerQueue中放入相關(guān)信息顯示,以確認(rèn)程序確實(shí)在運(yùn)轉(zhuǎn)。