阻塞隊列與普通隊列的區別在於,當隊列是空的時,從隊列中獲取元素的操作將會被阻塞,或者當隊列是滿時,往隊列裏添加元素的操作會被阻塞。
ArrayBlockingQueue
//數組結構組成的有界阻塞隊列
public class ArrayBlockingQueue_Demo {
public static void main(String[]args)throws InterruptedException{
//大小固定,有邊的。
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(17);
queue.offer("Liu");
queue.offer("Jun");
queue.offer("South");
// add() 隊尾添加元素,成功返回 true ,失敗拋出異常。
boolean add = queue.add("add");
// offer() 隊尾新添加元素。返回true表示添加成功,false表示添加失敗,不會拋出異常。
boolean offer1 = queue.offer("offer");
// offer() 隊尾新添加元素,如果隊列中沒有可用空間,當前線程就等待,如果等待時間超過timeout了,那麼返回false,表示添加失敗。
boolean offer2 = queue.offer("offer",3,TimeUnit.SECONDS);
// put() 向隊列末尾新添加元素,如果隊列已滿,當前線程就等待(阻塞線程)。響應中斷異常,無返回值。
queue.put("put");
// remove() 移除頭部元素,如果爲null則拋出異常,也可移除已知元素。
boolean remove = queue.remove("remove");
// poll() 移除頭部元素並返回。如果null不會拋異常,會返回null。
String poll1 = queue.poll();
// poll() 返回並移除隊列第一個元素,如果隊列是空的,就前線程就等待。 如果等待時間超過timeout了,那麼返回false,表示獲取元素失敗
String poll2 = queue.poll(3,TimeUnit.SECONDS);
// element() 獲取頭部元素,如果是null,拋出異常,不會刪除元素。
String element = queue.element();
// peek() 獲取頭部元素,不會刪除元素。
String peek = queue.peek();
// take() 如果隊列爲空則等待,否則移除頭元素。
String take = queue.take();
// remainingCapacity() 還剩多少空間
int size = queue.remainingCapacity();
}
}
LinkedBlockingDeque
//鏈表結構組成的雙向阻塞隊列
public class LinkedBlockingDeque_Demo {
public static void main(String[]args)throws InterruptedException{
//自動擴容
LinkedBlockingDeque<String> queue = new LinkedBlockingDeque();
queue.offer("Jun");
queue.offer("South");
//add() 如果隊列已滿,報java.lang.IllegalStateException: Queue full 錯誤。
boolean add = queue.add("add");
//offer() 如果隊列已滿,程序正常運行,只是不再新增元素。
boolean offer1 = queue.offer("offer1");
boolean offer2 = queue.offer("offer2",2, TimeUnit.SECONDS);
//put() 如果隊列已滿,阻塞。
queue.put("put");
//remove() 移除頭部元素,如果爲null拋出異常。
boolean remove = queue.remove("remove");
//poll() 移除頭部元素,隊列爲空時返回null。
String poll = queue.poll();
//獲取頭部元素,如果是null則拋異常。不會刪除元素。
String element = queue.element();
//獲取頭部元素,不刪除元素。隊列爲空時返回null。
String peek = queue.peek();
// 移除頭部元素。當隊列爲空,阻塞。
String take = queue.take();
}
}
LinkedBlockingQueue
//鏈表結構組成的有界阻塞隊列
public class LinkedBlockingQueue_Demo {
public static void main(String[]args)throws InterruptedException{
// 如果給定長度,則是定長。若不給定長度,會自動擴容。
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
queue.offer("Jun");
queue.offer("South");
//add() 如果隊列已滿,報java.lang.IllegalStateException: Queue full 錯誤。
boolean add = queue.add("add");
//offer() 如果隊列已滿,程序正常運行,只是不再新增元素。
boolean offer1 = queue.offer("offer1");
boolean offer2 = queue.offer("offer2",2, TimeUnit.SECONDS);
//put() 如果隊列已滿,阻塞。
queue.put("put");
//remove() 移除頭部元素,如果爲null拋出異常。
boolean remove = queue.remove("remove");
//poll() 移除頭部元素,隊列爲空時返回null。
String poll = queue.poll();
//獲取頭部元素,如果是null則拋異常。不會刪除元素。
String element = queue.element();
//獲取頭部元素,不刪除元素。隊列爲空時返回null。
String peek = queue.peek();
// 移除頭部元素。當隊列爲空,阻塞。
String take = queue.take();
}
}
LinkedTransferQueue
//鏈表結構組成的無界阻塞隊列
public class LinkedTransferQueue_Demo {
public static void main(String[]args)throws InterruptedException{
//自動擴容
LinkedTransferQueue<String> queue = new LinkedTransferQueue<>();
//add() 隊尾插元素,永遠返回true。
boolean add = queue.add("add");
//offer() 隊尾插元素,永遠返回true。
boolean offer1 = queue.offer("offer1");
boolean offer2 = queue.offer("offer2",2, TimeUnit.SECONDS);
//put() 隊尾插元素,永遠返回true。
queue.put("put");
//在隊尾插元素,沒有被消費,則等待。
queue.transfer("transfer");
//remove() 移除頭部元素,如果爲null拋出異常。
boolean remove = queue.remove("remove");
//poll() 移除頭部元素,隊列爲空時返回null。
String poll = queue.poll();
//獲取頭部元素,如果是null則拋異常。不會刪除元素。
String element = queue.element();
//獲取頭部元素,不刪除元素。隊列爲空時返回null。
String peek = queue.peek();
// 移除頭部元素。當隊列爲空,阻塞。
String take = queue.take();
}
}
PriorityBlockingQueue
//支持優先級排序的無界阻塞隊列
public class PriorityBlockingQueue_Demo {
public static void main(String[]args)throws InterruptedException{
//可指定長度,會自動擴容,無邊。
PriorityBlockingQueue<String> queue = new PriorityBlockingQueue<String>();
queue.offer("Jun");
queue.offer("Liu");
queue.offer("South");
// offer() 成功返回true,除非內存溢出否則不會返回false。
boolean offer1 = queue.offer("offer1");
boolean offer2 = queue.offer("offer2",3, TimeUnit.SECONDS);
// add() 調用 offer() 方法
boolean add = queue.add("add");
// put() 調用offer() 方法,無返回值。
queue.put("put");
// remove() 刪除頭部元素或指定刪除元素,如果爲null則拋異常。
boolean remove = queue.remove("offer1");
// poll() 移除頭部元素並返回。
String poll = queue.poll();
// element() 獲取頭部元素,如果是null,拋出異常,不會刪除元素。
String element = queue.element();
// peek() 獲取頭部元素,不會刪除元素。
String peek = queue.peek();
// take() 如果隊列爲空則等待,否則移除頭元素。
String take = queue.take();
}
}
SynchronousQueue
//沒有容量,是無緩衝等待隊列,是一個不存儲元素的阻塞隊列,會直接將任務交給消費者,必須等隊列中的添加元素被消費後才能繼續添加新的元素。
//插入操作put必須等移除操作take,反之亦然。
//不存儲元素的的阻塞隊列
public class SynchronousQueue_Demo {
public static void main(String[]args)throws InterruptedException{
SynchronousQueue<String> queue = new SynchronousQueue<String>();
// offer() 往queue裏放一個element後立即返回,如果碰巧這個element被另一個thread取走了,offer方法返回true,認爲offer成功;否則返回false。
boolean offer1 = queue.offer("offer1");
// offer(3, TimeUnit.SECONDS) 往queue裏放一個element但是等待指定的時間後才返回,返回的邏輯和offer()方法一樣。
boolean offer2 = queue.offer("offer2",2, TimeUnit.SECONDS);
// put() 往queue放進去一個element以後就一直wait直到有其他thread進來把這個element取走。
queue.put("put");
// remove()和removeAll() 永遠是false。
String remove = queue.remove();
// peek() 永遠返回null。
String peek = queue.peek();
// poll() 取出並且remove掉queue裏的element(認爲是在queue裏的。。。),只有到碰巧另外一個線程正在往queue裏offer數據或者put數據的時候,該方法纔會取到東西。否則立即返回null。
String poll = queue.poll();
// take() 取出並且remove掉queue裏的element(認爲是在queue裏的。。。),取不到東西他會一直等。
String take = queue.take();
// iterator() 永遠返回空,因爲裏面沒東西。
// isEmpty()永遠是true。
// remainingCapacity() 永遠是0。
}
}
DelayQueue
/*
DelayQueue 是一個無界阻塞隊列,要添加進去的元素必須實現 Delayed 接口,只有在延遲期滿時才能從中提取元素。
該隊列的頭部 是延遲期滿後保存時間最長的 Delayed 元素。
如果延遲都還沒有期滿,則隊列沒有頭部,並且 poll 將返回 null。
當一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小於等於 0 的值時,表示該元素到期了。
無法使用 take 或 poll 移除未到期的元素,也不會將這些元素作爲正常元素對待。例如,size 方法同時返回到期和未到期元素的計數。
此隊列不允許使用 null 元素。*/
//使用優先級隊列實現的無界阻塞隊列
public class DelayQueue_Demo{
static class DelayElement<E> implements Delayed{
private final E e;
private long start = System.currentTimeMillis();
private final long time;
public DelayElement(E e, long time) {
this.e = e;
this.time = time + start;
}
static <T> DelayElement<T> of(T e,long delay){
return new DelayElement<>(e,delay);
}
/**
* 需要實現的接口,獲得延遲時間 用過期時間-當前時間
* @param unit
*/
public long getDelay(TimeUnit unit) {
long diff = time - System.currentTimeMillis();
return unit.convert(diff,TimeUnit.MILLISECONDS);
}
/**
* 用於延遲隊列內部比較排序 當前時間的延遲時間 - 比較對象的延遲時間
* @param delayedObject
*/
public int compareTo(Delayed delayedObject) {
DelayElement that = (DelayElement) delayedObject;
if (this.time < that.getExpireTime()){
return -1;
}else if (this.time > that.getExpireTime()){
return 1;
}else {
return 0;
}
}
public E getData(){
return e;
}
public long getExpireTime(){
return time;
}
}
public static void main(String[]args)throws InterruptedException{
DelayQueue<DelayElement<String>> queue = new DelayQueue();
//offer() 隊位插元素,如果爲null則拋異常。
boolean offer = queue.offer(null);
// add() 隊位插元素,如果爲null則拋異常。
boolean add = queue.add(DelayElement.of("add",1000));
// put() 隊位插元素,如果爲null則拋異常。
queue.put(DelayElement.of("add",1000));
// remove() 移除頭部元素,爲null則拋異常。
DelayElement remove = queue.remove();
// poll() 移除頭部元素並返回。
DelayElement poll = queue.poll();
// element() 獲取頭部元素,如果是null則拋異常。不會刪除元素。
DelayElement element = queue.element();
// peek() 獲取頭部元素,不會刪除。
DelayElement peek = queue.peek();
// take() 獲取頭部元素,有就拿走,沒有就阻塞等待。
DelayElement take = queue.take();
}
}