BlockingQueue
佇列(Queue)是個先前先出(First In First Out, FIFO)的資料結構。在JDK 5.0中新增了Blocking Queue,在多執行緒的情況下,如果Blocking Queue的內容為空,而有個執行緒試圖從Queue中取出元素,則該執行緒會被Block,直到Queue有元素時才解除Block,反過來說,如果 Blocking Queue滿了,而有個執行緒試圖再把資料填入Queue中,則該執行緒會被Block,直到Queue中有元素被取走後解除Block。
BlockingQueue的幾個主要操作為下:
方法 |
說明 |
add |
加入元素,如果佇列是滿的,則丟出IllegalStateException |
remove |
傳回並從佇列移除元素,如果佇列是空的,則丟出NoSuchElementException |
element |
傳回元素,如果佇列是空的,則丟出NoSuchElementException |
offer |
加入元素並傳回true,如果佇列是滿的,則傳回false |
poll |
傳回並從佇列移除元素,如果佇列是空的,則傳回null |
peek |
傳回元素,如果佇列是空的,則傳回null |
put |
加入元素,如果佇列是滿,就block |
take |
傳回並移除元素,如果佇列是空的,就block |
在java.util.concurrent下提供幾種不同的Blocking Queue,ArrayBlockingQueue要指定容量大小來建構,LinkedBlockingQueue預設沒有容量上限,但也可以指定容量上限,PriorityBlockingQueue嚴格來說不是Queue,因為它是根據優先權(Priority)來移除元素。
在這邊以 wait()、notify() 中的生產者、消費者程式為例,使用BlockQueue來加以改寫,好處是我們不用親自處理wait、notify的細節,首先生產者改寫如下:
package onlyfun.caterpillar;
import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable {
private BlockingQueue<Integer> queue;
public Producer(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();
}
}
}
}
消費者類別改寫如下:
package onlyfun.caterpillar;
import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable {
private BlockingQueue<Integer> queue;
public Consumer(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();
}
}
}
}
可以使用下面這個程式來簡單的測試一下:
package onlyfun.caterpillar;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueDemo {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1);
Thread producerThread = new Thread(
new Producer(queue));
Thread consumerThread = new Thread(
new Consumer(queue));
producerThread.start();
consumerThread.start();
}
}
posted on 2008-08-05 09:01
bcterry 阅读(170)
评论(0) 编辑 收藏