14 併發Queue

1.1 併發Queue

在併發隊列上JDK提供了兩套實現,一個是以ConcurrentLinkedQueue爲代表的高性能隊列,一個是以BlockingQueue接口爲代表的阻塞隊列,無論哪種都繼承自Queue。

 

1.2 ConcurrentLinkedQueue

ConcurrentLinkedQueue:是一個適用於高併發場景下的隊列,通過無鎖的方式,實現了高併發下的高性能,通常ConcurrentLinkedQueue性能好於BlockingQueue。它是一個基於鏈接節點的無界線程安全隊列。該隊列的元素遵循先進先出的原則。頭是最先加入的,尾是最近加入的,該隊列不允許null元素。

 

ConcurrentLinkedQueue重要方法:

add()和offer() 都是加入元素的方法(在ConcurrentLinkedQueue中這兩個方法沒有任何區別)

poll()和peek() 都是取頭元素節點,區別在於前者會刪除元素,後者不會。

 

1.3 BlockingQueue接口

ArrayBlockingQueue –基於數組實現的一個阻塞隊列,在創建ArrayBlockingQueue對象時必須制定容量大小以便緩存隊列中的數據對象,其內部沒有實現讀寫分離,即生產者和消費者不能完全並行。並且可以指定公平性與非公平性,默認情況下爲非公平的,即不保證等待時間最長的線程最優先能夠訪問隊列。 有界隊列


LinkedBlockingQueue–基於鏈表實現的一個阻塞隊列,在創建LinkedBlockingQueue對象時如果不指定容量大小,則默認大小爲Integer.MAX_VALUE。 內部採用分離鎖(讀寫分離兩個鎖),從而實現生產者和消費者操作的完全並行運行。無界隊列

 

SynchronousQueue –同步阻塞隊列,隊列大小爲1,一個元素要放到該隊列中必須有一個線程在等待獲取元素。


PriorityBlockingQueue無界阻塞隊列,它會按照元素的優先級對元素進行排序,按照優先級順序出隊,每次出隊的元素都是優先級最高的元素。 


DelayQueue –基於PriorityQueue實現的延遲隊列,是一個無界的阻塞隊列,用於放置實現了Delayed接口的對象,其中的對象只能在其到期時才能從隊列中取走。因此向隊列中插入時永遠不會阻塞,獲取時纔有可能被阻塞  


DelayedWorkQueue –該隊列爲ScheduledThreadPoolExecutor中的靜態內部類,ScheduledThreadPoolExecutor便是通過該隊列使得隊列中的元素按一定順序排列從而時延遲任務和週期性任務得以順利執行。 


BlockingDeque–雙向阻塞隊列的接口。 


TransferQueue–接口,定義了另一種阻塞情況:生產者會一直阻塞直到所添加到隊列的元素被某一個消費者所消費,而BlockingQueue只需將元素添加到隊列中後生產者便會停止被阻塞。

 

示例:

public class MyBlockingQueue {

 

public static void main(String[] args) throws InterruptedException {

ArrayBlockingQueue<String> array = new ArrayBlockingQueue<String>(5);//指定隊列大小

 

//array.offer("a",2,TimeUnit.SECONDS);//兩秒內加進去就返回true,否則返回false

array.put("b");

array.add("c");

array.add("d");

array.add("e");

/**

 * offer 可以是設定阻塞時間的

 * put 不具備該參數

 */

//兩秒內加進去就返回true,否則返回false

System.out.println(array.offer("a",2,TimeUnit.SECONDS));

//---------------------------------------------------------------------------------------------

LinkedBlockingQueue<String> q = new LinkedBlockingQueue<String>();//無界的,可指定大小,可不指定

 

//array.offer("a",2,TimeUnit.SECONDS);//兩秒內加進去就返回true,否則返回false

q.put("b");

q.add("c");

q.add("d");

q.add("e");

q.add("f");

//q.add("g");

List<String> list = new ArrayList<String>();

/**

 * 在q隊列中去3個值放到list中

 */

q.drainTo(list,3);

for(Iterator iterator = q.iterator();iterator.hasNext();) {

String string = (String)iterator.next();

System.out.println(string);

}

//------------------------------------------------------------------

/**

 * SynchronousQueue是不允許加元素的

如果一個take方法在阻塞中,那是可以加add方法的

 */

SynchronousQueue<String> sq = new SynchronousQueue<String>();

//------------------------------------------------------------------

PriorityBlockingQueue<String> pbq = new PriorityBlockingQueue<String>();

pbq.add("f");

pbq.add("e");

pbq.add("a");

for(String s : pbq) {

System.out.println(s);

//結果是afe,因爲該隊列採用得小頂堆,每次第一個元素取走後,再使得堆頂是最小的元素

//如果使用poll方法的話就會打印出有序的字符串

}

}

}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章