在講阻塞式隊列之前,首先理解什麼是JUC。
JUC是(java.util.concurrent的簡稱),是java1.5提供的一個處理線程的工具包及其子包。JUC的主要內容包括:阻塞式隊列、併發映射、鎖、執行器服務、原子性操作。本次給大家首先介紹的就是其中的阻塞式隊列。
阻塞式隊列(Blocking Queue)
顧名思義,“阻塞式”是對“隊列”的形容,主語還是“隊列”。所以它滿足隊列的基本特點:FIFO(FIRST IN FIRST OUT——先進先出)。除此之外,它在使用之前需要確定容量,且確定之後,容量不可變。
既然還提到了“阻塞”,那它一定有阻塞相關的特性:
1.如果隊列爲空,嘗試獲取元素會阻塞。
2.如果隊列已滿,嘗試添加元素會阻塞。
查詢java的api文檔:
BolockingQueue是一個接口,繼承了Collection、Iterable 、Queue接口,直接實現類主要有:ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等等。
對其中一個有代表性的ArrayBlockingQueue實現類進行簡單介紹。
阻塞式順序隊列—ArrayBlockingQueue
作爲一個容器,我們使用它的目地無法就是對它增、刪、改、查,來實現對數據的操作。
ArrayBlockingQueue提供了三類主要的添加數據的方法,分別爲:add put 以及offer。
用代碼演示它們之間的區別。
add
@Test
public void arayBlockingQueue() throws InterruptedException {
//使用時需要指定容量
BlockingQueue<Integer> arrbq=new ArrayBlockingQueue(5);
arrbq.add(1);
arrbq.add(4);
arrbq.add(5);
arrbq.add(7);
arrbq.add(8);
System.out.println(arrbq);
//數據已滿,繼續添加元素
arrbq.add(8);
System.out.println(arrbq);
}
執行效果:add方法是非阻塞的,如果隊列已滿,繼續添加元素會拋出Queue full異常:
put
//數據已滿,繼續添加元素
arrbq.put(8);
執行效果:add方法是阻塞的,如果隊列已滿,繼續添加元素會產生阻塞:
offer
//數據已滿,繼續添加元素
arrbq.offer(8);
執行效果:offer方法是非阻塞的,如果隊列已滿,繼續添加不會報錯,而且新添加的元素也不會添加到隊列中(存在返回值,添加成功返回true ,添加失敗返回false):
offer還重載了一個定時阻塞的方法,相信一看便懂,不再贅述。
除了添加元素,相對應的還有刪除元素。刪除元素的主要方法有:remove take poll
remove
/**
* Retrieves and removes the head of this queue. This method differs
* from {@link #poll poll} only in that it throws an exception if this
* queue is empty.
*
* @return the head of this queue
* @throws NoSuchElementException if this queue is empty
*/
從源碼的解釋可以看出,該方法將移除隊首元素,如果隊列爲空,拋出NoSuchElementException異常。
take
/**
* Retrieves and removes the head of this queue, waiting if necessary
* until an element becomes available.
*
* @return the head of this queue
* @throws InterruptedException if interrupted while waiting
*/
移除隊首元素,必要時將等待(也就是會產生阻塞),直到有元素可以獲取。
poll
/**
* Retrieves and removes the head of this queue,
* or returns {@code null} if this queue is empty.
*
* @return the head of this queue, or {@code null} if this queue is empty*/
*
移除隊首元素,如果有則移除,沒有則返回null。也是非阻塞的。
和offer對應,poll也重載了一個定時阻塞的方法:
總結
拋出異常 | 返回指定值 | 永久阻塞 | 定時阻塞 | |
---|---|---|---|---|
添加 | 如果隊列已滿,add拋出IllegalStateException | offer 添加成功返回 true ,添加失敗 false | put | offer |
移除 | 如果隊列爲空,remove拋出 NoSuchElementException | poll 隊列爲空返回null | take | poll |