1. 程式人生 > >ArrayBlockingQueue和LinkedBlockingQueue的區別及使用

ArrayBlockingQueue和LinkedBlockingQueue的區別及使用

BlockingQueue介面定義了一種阻塞的FIFO queue,每一個BlockingQueue都有一個容量,讓容量滿時往BlockingQueue中新增資料時會造成阻塞,當容量為空時取元素操作會阻塞。

ArrayBlockingQueue是一個由陣列支援的有界阻塞佇列。在讀寫操作上都需要鎖住整個容器,因此吞吐量與一般的實現是相似的,適合於實現“生產者消費者”模式。

LinkedBlockingQueue是基於連結串列的阻塞佇列,同ArrayListBlockingQueue類似,其內部也維持著一個數據緩衝佇列(該佇列由一個連結串列構成),當生產者往佇列中放入一個數據時,佇列會

從生產者手中獲取資料,並快取在佇列內部,

而生產者立即返回;只有當佇列緩衝區達到最大值快取容量時(LinkedBlockingQueue可以通過建構函式指定該值),才會

阻塞生產者佇列,直到消費者從佇列中消費掉一份資料,生產者執行緒會被喚醒,反之對於消費者這端的處理也基於同樣的原理。而LinkedBlockingQueue之所以能夠高效

的處理併發資料,還因為其對於生產者端和消費者端分別採用了獨立的鎖來控制資料同步,這也意味著在高併發的情況下生產者和消費者可以並行地操作佇列中的資料,

以此來提高整個佇列的併發效能。

ArrayBlockingQueue和LinkedBlockingQueue的區別:

1. 佇列中鎖的實現不同

    ArrayBlockingQueue實現的佇列中的鎖是沒有分離的,即生產和消費用的是同一個鎖;

    LinkedBlockingQueue實現的佇列中的鎖是分離的,即生產用的是putLock,消費是takeLock

2. 在生產或消費時操作不同

    ArrayBlockingQueue實現的佇列中在生產和消費的時候,是直接將列舉物件插入或移除的;

    LinkedBlockingQueue實現的佇列中在生產和消費的時候,需要把列舉物件轉換為Node<E>進行插入或移除,會影響效能

3. 佇列大小初始化方式不同

    ArrayBlockingQueue實現的佇列中必須指定佇列的大小;

    LinkedBlockingQueue實現的佇列中可以不指定佇列的大小,但是預設是Integer.MAX_VALUE

常用API:

offer

將元素插入佇列,成功返回true,如果當前沒有可用的空間,則返回false

offer(E e, long timeout, TimeUnit unit) 

將元素插入佇列,在到達指定的等待時間前等待可用的空間

E poll(long timeout, TimeUnit unit) 

獲取並移除佇列的頭部,在指定的等待時間前等待可用的元素

void put(E e) 

將元素插入佇列,將等待可用的空間(堵塞)

take() 

獲取並移除佇列的頭部,在元素變得可用之前一直等待(堵塞)


public class BlockingQueueTest {
	private static ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(5, true); //最大容量為5的陣列堵塞佇列
	//private static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(5);
	
	private static CountDownLatch producerLatch; //倒計時計數器
	private static CountDownLatch consumerLatch;
	
	public static void main(String[] args) {
		BlockingQueueTest queueTest = new BlockingQueueTest();
		queueTest.test();
	}
	
	private void test(){
		producerLatch = new CountDownLatch(10); //state值為10
		consumerLatch = new CountDownLatch(10); //state值為10
		
		Thread t1 = new Thread(new ProducerTask());
		Thread t2 = new Thread(new ConsumerTask());

		//啟動執行緒
		t1.start();
		t2.start();
		
		try {
			System.out.println("producer waiting...");
			producerLatch.await(); //進入等待狀態,直到state值為0,再繼續往下執行
			System.out.println("producer end");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		try {
			System.out.println("consumer waiting...");
			consumerLatch.await(); //進入等待狀態,直到state值為0,再繼續往下執行
			System.out.println("consumer end");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		//結束執行緒
		t1.interrupt(); 
		t2.interrupt();
		
		System.out.println("end");
	}
	
	//生產者
	class ProducerTask implements Runnable{
		private Random rnd = new Random();
		
		@Override
		public void run() {
			try {
				while(true){
					queue.put(rnd.nextInt(100)); //如果queue容量已滿,則當前執行緒會堵塞,直到有空間再繼續
					
					//offer方法為非堵塞的
					//queue.offer(rnd.nextInt(100), 1, TimeUnit.SECONDS); //等待1秒後還不能加入佇列則返回失敗,放棄加入
					//queue.offer(rnd.nextInt(100));
					
					producerLatch.countDown(); //state值減1
					//TimeUnit.SECONDS.sleep(2); //執行緒休眠2秒
				}
			} catch (InterruptedException e) {
				//e.printStackTrace();
			}  catch (Exception ex){
				ex.printStackTrace();
			}
		}
	}
	
	//消費者
	class ConsumerTask implements Runnable{
		@Override
		public void run() {
			try {
				while(true){
					Integer value = queue.take(); //如果queue為空,則當前執行緒會堵塞,直到有新資料加入
					
					//poll方法為非堵塞的
					//Integer value = queue.poll(1, TimeUnit.SECONDS); //等待1秒後還沒有資料可取則返回失敗,放棄獲取
					//Integer value = queue.poll();
					
					System.out.println("value = " + value);
					
					consumerLatch.countDown(); //state值減1
					TimeUnit.SECONDS.sleep(2); //執行緒休眠2秒
				}
			} catch (InterruptedException e) {
				//e.printStackTrace();
			} catch (Exception ex){
				ex.printStackTrace();
			}
		}
	}
	
}


相關推薦

ArrayBlockingQueueLinkedBlockingQueue區別使用

BlockingQueue介面定義了一種阻塞的FIFO queue,每一個BlockingQueue都有一個容量,讓容量滿時往BlockingQueue中新增資料時會造成阻塞,當容量為空時取元素操作會阻塞。 ArrayBlockingQueue是一個由陣列支援的有界阻塞佇

ArrayBlockingQueueLinkedBlockingQueue

分離 一個人 高效 一個 模型 空間 非阻塞 其中 影響 1、BlockingQueue接口定義了一種阻塞的FIFO queue ArrayBlockingQueue和LinkedBlockingQueue的區別: 1. 隊列中鎖的實現不同 ArrayBlockin

.net core學習筆記《sdkruntime區別使用CLI在Ubuntu上快速搭建Console,WebApi,MVC三大應用模型》

img 裝包 new 來看 tin console bubuko file 接下來 一、需要安裝的軟件 1、虛擬機安裝Ubuntu系統(本人用的是vmware-14.1.12和buntu-18.04) 2、Xshell或 Putty(連接ssh服務) 3、FileZilla

mysql :==的區別統計查詢結果行號

變數初始化:@rownum:=0 累加,標記行號:@rownum:[email protected]+1 SELECT rank FROM ( SELECT id, @rownum := CAST(@rownum AS SIGNED) + 1 AS rank

getRequestDispatcher sendRedirect區別路徑問題

轉載自:https://www.cnblogs.com/w-wfy/p/6387538.html getRequestDispatcher 和sendRedirect區別   getRequestDispatcher是伺服器內部跳轉,位址列資訊不變,只能跳轉到web應用內的網頁

說說&&& |||的區別 關於位操作符的使用總結

參考資料: 張孝祥老師整理的Java就業面試題大全 Java開發實戰經典(李興華老師) 及http://hi.baidu.com/onjee/blog/item/4e902d1f3450040f304e15ca.html package src;/** 本示例演示&和&

阻塞佇列BlockingQueue以及它的兩個重要實現類ArrayBlockingQueueLinkedBlockingQueue

多執行緒環境中,通過佇列可以很容易實現資料共享,比如經典的“生產者”和“消費者”模型中,通過佇列可以很便利地實現兩者之間的資料共享。假設我們有若干生產者執行緒,另外又有若干個消費者執行緒。如果生產者執行緒需要把準備好的資料共享給消費者執行緒,利用佇列的方式來傳遞資料,就可以很方便地解決他們之間的資料

js中!!!的區別用法簡介

js中!的用法是比較靈活的,它除了做邏輯運算常常會用!做型別判斷,可以用!與上物件來求得一個布林值, 1、!可將變數轉換成boolean型別,null、undefined和空字串取反都為false,其餘都為true。 複製程式碼 1 !null=true 2 3

is==的區別,編碼相關內容總結

is和==的區別 is 比較的是記憶體地址 == 比較的是內容 當兩個變數指向同一個物件的時候. is是True, ==也是True 編碼   1. ascii. 有: 數字, 字母, 特殊字元. 8bit 1byte 128 最前面是0 2. gbk. 包含: ascii, 中文(主要),

伺服器TIME_WAITCLOSE_WAIT區別解決方案

系統上線之後,通過如下語句檢視伺服器時,發現有不少TIME_WAIT和CLOSE_WAIT。 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 列印顯示如下: TIME_WAIT

SynchronousQueueLinkedBlockingQueue區別

在多執行緒開發中,會用到SynchronousQueue(new CachedThreadPool())和LinkedBlockingQueue(new FixedThreadPoll()) 我們來簡單分析一下這兩個佇列的區別 SynchronousQueue:   offer():當執行緒offer操

JSONObjectJSONArray區別基本用法

一、JSONObject和JSONArray的資料表示形式 JSONObject的資料是用 {  } 來表示的,         例如:   { "id" : "123", "courseID" : "huangt-test", "title" : "提交作業", "

NPM依賴包版本號 區別最佳實踐

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!                     你會發現很多專案的依賴包版本號前面會加上~,或者是^,以Angular2為例: 那麼~和^的作用和區別是什麼呢?~會匹配最近的小版本依賴包,比如~1.

ArrayListLinkedList區別使用場景

1、ArrayList是基於陣列實現的,其建構函式為: private transient Object[] elementData; private int size; ArryList初始化時,elementData陣列大小預設為10; 每次add()時,先呼叫ensu

Java IO:BIONIO區別各自應用場景

引言BIO和NIO是兩種不同的網路通訊模型,現如今NIO已經大量應用在Jetty、ZooKeeper、Netty等開源框架中。一個面向流、一個面向緩衝區一個是阻塞式的、一個非阻塞一個沒有io多路複用器、一個有下面通過一個例子解釋兩者區別:假設當前服務端程式需要同時從與多個客戶

區別 Linux下編譯iostream.h的方法

# g++34example.cpp In file included from /usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../include/c++/3.4.6/backward/iostream.h:31, from main.cpp:8: /us

Java web專案的classpathclasspath*的區別,***的區別如何查詢Java資原始檔路徑

這裡的專案都是Web專案才有classpath: web專案中的src路徑下的檔案在編譯後會放到WEB-INF/classess路徑下,預設的classpath路徑就是WEB-INF/classess路徑,直接放到WEB-INF下的話,是不在classpath下的。用ClassPathXmlApp

JDK原始碼分析—— ArrayBlockingQueue LinkedBlockingQueue

招賢納士: 我們叫數瀾 我們核心技術團隊來自阿里、華為、金蝶、移動、GE等 我們獲得來自阿里巴巴集團聯合創始人、湖畔山南總裁謝世煌、IDG合夥人牛奎光、洪泰等投資 我們的官網:https://www.dtwave.com 我們提供:期權、五險一金、試用期全薪、商業保險、免

堵塞佇列之ArrayBlockingQueueLinkedBlockingQueue解析

線上程池建立的時候,需要傳一個堵塞佇列來維護需要執行的執行緒任務,其中最常用的是ArrayBlockingQueue和LinkedBlockingQueue。他們都繼承了BlockingQueue介面。 ArrayBlockingQueue 一個有邊

sizeofstrlen()區別用法

//sizeof是以位元組為單位計算變數或型別所佔記憶體大小,它是屬於C語言運算子系列;而strlen()是一個函式,是計算字串長度(也是以位元組為單位,但略有區別);比如: char array[] = {"ILOVE"}; printf("%d", strlen(array)); //值為5