Java java.util.currency
包中的BlockingQueue
接口意味着線程能夠在一個隊列中添加和提取對象.在接下來的段落中,咱們將學習如何使用BlockingQueue
接口.html
BlockingQueue典型應用是用於一個線程生產對象,另外一個線程消費對象.java
下面是一個原理描述圖:併發
一個阻塞隊列伴隨着一個線程往隊列中添加對象,另外一個線程從隊列中提取對象.ide
生產線程負責生產新對象併發它添加進隊列中,直到達到隊列所能容納的邊界值爲止.即達到容量限制.若是隊列達到容量限制,則生產線程在插入新對象時將會發生阻塞.直到有一個消費線程從隊列中取走一個對象爲止.學習
消費線程負責從阻塞隊列中取出對象並處理它們.若是消費線程嘗試從空隊列中取出空隊列,那麼消費線程將會阻塞直到生產線程往隊列中放入一個對象爲止.this
一個阻塞隊列包含四種大相徑庭的方法集,用於完成在隊列中插入,移除和檢查元素.每種集合的不一樣之處在於操做請求不能被當即執行時的不一樣行爲.下面是這些方法的列表:spa
Throws Exception | Special Value | Blocks | Times Out | |
---|---|---|---|---|
Insert | add(o) | offer(o) | put(o) | offer(o, timeout, time unit) |
Remove | remove(o) | poll() | take() | poll(timeout, timeunit) |
Examine | element() | peek() |
四種不一樣的行爲結合以下:線程
不能插入null
到BlockingQueue中.若是你這麼作了,BlockingQueue將拋出一個NullPointerException
.code
固然咱們也可以訪問BlockingQueue的全部元素, 不僅是隊頭和隊尾. 例如, 你須要出隊一個對象用於執行,但你的應用決定取消它.那麼你仍然可使用相似remove(o)方法來移除隊列中指定的對象.然而這不是很高效,因此你不該該使用這類方法, 除非你真的須要這麼作.cdn
BlockingQueue只是一個接口, 因此你須要使用它衆多實現的其中一種來使用它.java.util.concurrency
包中有以下幾種BlockingQueue的接口實現(在Java6中):
下面是一個Java BlockingQueue的實例. 實例中使用BlockingQueue接口的實現類,ArrayBlockingQueue.
首先,BlockingQueueExample類中分別啓動一個生產和消費線程.生產線程負責插入字符串到共享BlockingQueue中,而消費線程則負責取走它們.
public class ArrayBlockingQueueExample {
public static void main(String[] args) {
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1024);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
new Thread(producer).start();
new Thread(consumer).start();
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
複製代碼
下面是Producer類.注意咱們每調用一次put()就會讓線程睡眠一秒.這會致使消費線程在隊列中等待對象時發生阻塞.
public class Producer implements Runnable {
private ArrayBlockingQueue<String> queue;
public Producer(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
queue.put("1");
Thread.sleep(1000);
queue.put("2");
Thread.sleep(1000);
queue.put("3");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
複製代碼
下面是Consumer類.它只是負責從隊列中取出字符串並經過System.out打印出來.
package org.menfre;
import java.util.concurrent.ArrayBlockingQueue;
public class Consumer implements Runnable {
private ArrayBlockingQueue<String> queue;
public Consumer(ArrayBlockingQueue<String> queue){
this.queue = queue;
}
@Override
public void run() {
try {
System.out.println(queue.take());
System.out.println(queue.take());
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
複製代碼
該系列博文爲筆者複習基礎所著譯文或理解後的產物,複習原文來自Jakob Jenkov所著Java.util.concurrent