005併發容器類 BlockingQueue介面

2021-09-24 14:04:12 字數 3166 閱讀 1720

concurrentlinkedqueue(無界佇列):

//1.高效能的無阻塞無界佇列concurrentlinkedqueue

//無界佇列不用定義長度

concurrentlinkedqueueclq = new concurrentlinkedqueue();

//新增元素有兩種方法offer()和add(),他們沒有區別

clq.offer("a");

clq.add("b");

clq.add("c");

clq.add("d");

//獲取資料,使用poll()獲取頭部資料,並且將頭部資料移除

system.out.println("頭部取出元素:"+clq.poll());//從頭部取出乙個元素,並且從容器本身移除

system.out.println("容器長度:"+clq.size());

system.out.println("頭部取出元素:"+clq.peek());//從頭部取出乙個元素,但不會從容器本身移除

system.out.println("容器長度:"+clq.size());

arrayblockingqueue(有界佇列):基於陣列的阻塞佇列實現,在arrayblockingqueue內部維護了乙個有限長度的陣列(即定長陣列),以便快取對列中的資料物件,其內部沒有實現讀寫分離,也就意味著生產和消費不能完全並行,其長度是需要定義的,可以指定先進先出(fifo),其屬於有界佇列,應用場景很多。

//2.基於阻塞- 有界佇列arrayblockingqueue,需要定義長度arrayblockingqueue<>(5)

/*其為有界佇列,單執行緒操作,不支援高併發

* 不能實現生產和消費並行*/

//arrayblockingqueue內部結構是維護這乙個有界的陣列

arrayblockingqueueabq = new arrayblockingqueue<>(5);

//新增元素

abq.put("a");

abq.add("b");

abq.add("c");

abq.add("d");

abq.add("e");

//使用offer新增元素,如果可以新增返回true,如果不可以返回false,此處應用帶有延遲時間和時間戳的offer方法

system.out.println(abq.offer("f", 2, timeunit.seconds));

//應用drainto進行佇列拷貝

arrayblockingqueueabq1 = new arrayblockingqueue<>(5);

abq.drainto(abq1,3);//將abq容器中的元素拷貝3個到abq1中

//迴圈佇列

for(iterator iterator = abq1.iterator();iterator.hasnext();)

linkedblockingqueue:基於鍊錶的阻塞佇列,同arrayblockingqueue類似,其內部也維持著乙個資料緩衝佇列(該佇列由乙個鍊錶構成),linkedblockingqueue之所以能夠高效的處理併發資料,是因為其內部實現採用分離鎖(讀寫分離兩個鎖),從而實現生產者和消費者操作的完全並行執行,他是乙個無界佇列。

/*3.基於阻塞- 無界佇列linkedblockingqueue

* 基於鍊錶的阻塞佇列linkedblockingqueue,內部維護著鍊錶,

* 能夠高效處理併發資料,其內部實現分離鎖(讀寫分離兩個鎖),從而

* 實現生產者和消費者操作完全並行;

* 使用方法基本等同於arrayblockingqueue

*/linkedblockingqueuelbq = new linkedblockingqueue<>();

lbq.put("a");

lbq.add("b");

lbq.add("c");

lbq.add("d");

lbq.add("e");

lbq.add("f");

lbq.add("g");

system.out.println(lbq.offer("h", 1, timeunit.seconds));

system.out.println("容器大小"+lbq.size());

system.out.println("poll()從頭部取出元素"+lbq.poll());

system.out.println("poll方法取出元素後容器大小"+lbq.size());

system.out.println("peek()從頭部取出元素"+lbq.peek());

system.out.println("peek方法取出元素後容器大小"+lbq.size());

linkedblockingqueuelbq1 = new linkedblockingqueue<>();

lbq.drainto(lbq1,3);

for(iterator iterator = lbq1.iterator();iterator.hasnext();)

synchronousqueue:一種沒有緩衝的佇列,生產者產生的資料直接會被消費者獲取並消費

/*4.沒有快取的佇列 synchronousqueue(不能盛放任何元素的阻塞佇列)

* 生產者生產的資料直接會被消費者獲取並消費

* 它同時也是一種阻塞佇列

* 實現快速的獲取與投遞機制:正常場景下必須有乙個a獲取元素執行緒阻塞在容器中,

* 然後b投遞元素執行緒投遞後啟用a執行緒完成獲取;如果b投遞執行緒先投遞就會出現異常;

*/synchronousqueuesq = new synchronousqueue();

"a");//直接新增報 queue full異常

//定義獲取元素的執行緒並啟動,進入等待

new thread(new runnable() catch (interruptedexception e)

}},"t1").start();

//定義新增元素的執行緒,並啟用獲取元素的執行緒

new thread(new runnable()

},"t2").start();

}   

關於阻塞佇列與非阻塞佇列可以參考:

同步類容器和併發類容器

同步類容器都是執行緒安全的,但是某些場景下可能需要加鎖來保護復合操作。復合類操作如 迭代 反覆訪問元素,遍歷完容器中所有的元素 跳轉 根據指定的順序找到當前元素的下乙個元素 以及條件運算。這些復合操作在多執行緒併發地修改容器時,可能會表現出意外的行為,最經典的便是concurrentmodifica...

同步類容器和併發類容器

同步類容器都是執行緒安全的,但在某些場景下可能需要加鎖來保護復合操作。復合類操作。如 迭代 反覆訪問元素,遍歷完容器中所有的元素 跳轉 根據指定的順序找到當前元素的下乙個元素 以及條件運算。這些復合操作在多執行緒併發地修改容器時,可能會表現出意外的行為,最經典的便是concurrentmodific...

同步類容器和併發類容器

同步類容器都是執行緒安全的,同步容器類包括 vector 和 hashtable,二者都是早期 jdk 的一部分,此外還包括在 jdk1.2 當中新增的一些功能相似的類,這些同步的封裝類是由 collections.synchronized 等工廠方法建立的。但在某些場景下可能需要加鎖來保護復合操作...