java并發(fā)編程工具類JUC之ArrayBlockingQueue
Java BlockingQueue接口java.util.concurrent.BlockingQueue表示一個可以存取元素,并且線程安全的隊列。換句話說,當(dāng)多線程同時從 JavaBlockingQueue中插入元素、獲取元素的時候,不會導(dǎo)致任何并發(fā)問題(元素被插入多次、處理多次等問題)。
從java BlockingQueue可以引申出一個概念:阻塞隊列,是指隊列本身可以阻塞線程向隊列里面插入元素,或者阻塞線程從隊列里面獲取元素。比如:當(dāng)一個線程嘗試去從一個空隊列里面獲取元素的時候,這個線程將被阻塞直到隊列內(nèi)元素數(shù)量不再為空。當(dāng)然,線程是否會被阻塞取決于你調(diào)用什么方法從BlockingQueue獲取元素,有的方法會阻塞線程,有的方法會拋出異常等等,下文我們會詳細(xì)介紹。
類ArrayBlockingQueue
是BlockingQueue
接口的實(shí)現(xiàn)類,它是有界的阻塞隊列,內(nèi)部使用數(shù)組存儲隊列元素。這里的“有界”是指存儲容量存在上限,不能無限存儲元素。在同一時間內(nèi)存儲容量存在著一個上限值,這個上限制在初始實(shí)例化的時候指定,之后便不能修改了。
ArrayBlockingQueue
內(nèi)部采用FIFO (First In, First Out)先進(jìn)先出的方法實(shí)現(xiàn)隊列數(shù)據(jù)的存取,隊首的元素是在隊列中保存時間最長的元素對象,隊尾的元素是在隊列中保存時間最短的元素對象。
下面的代碼說明如何初始化一個ArrayBlockingQueue
,并向其中添加一個對象:
BlockingQueue queue = new ArrayBlockingQueue(1024); queue.put("1"); //向隊列中添加元素 Object object = queue.take(); //從隊列中取出元素
BlockingQueue
可以通過泛型來限定隊列中存儲數(shù)據(jù)的類型,下面的代碼以String為泛型,表示該隊列只能存儲String類型。
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1024); queue.put("1"); String string = queue.take();
實(shí)現(xiàn)一個生產(chǎn)消費(fèi)的實(shí)例
在前面的文章中我們曾經(jīng)講過:BlockingQueue經(jīng)常被用于生產(chǎn)消費(fèi)的緩沖隊列。下面我們就使用ArrayBlockingQueue
來真正的實(shí)現(xiàn)一個生產(chǎn)消費(fèi)的例子。
類BlockingQueueExample
開啟兩個獨(dú)立線程,一個是Producer
生產(chǎn)者線程,負(fù)責(zé)向隊列中添加數(shù)據(jù);另一個是Consumer
消費(fèi)者線程,負(fù)責(zé)從隊列中取出數(shù)據(jù)進(jìn)行處理。
public class BlockingQueueExample { public static void main(String[] args) throws Exception { //使用ArrayBlockingQueue初始化一個BlockingQueue,指定容量的上限為1024 BlockingQueue queue = new ArrayBlockingQueue(1024); Producer producer = new Producer(queue); //生產(chǎn)者 Consumer consumer = new Consumer(queue); //消費(fèi)者 new Thread(producer).start(); //開啟生產(chǎn)者線程 new Thread(consumer).start(); //開啟消費(fèi)者線程 Thread.sleep(4000); } }
類Producer
為生產(chǎn)者,每隔10秒鐘使用put()
方法向隊列中放入一個對象,放入三次。在這10秒的間隔內(nèi),隊列數(shù)據(jù)被消費(fèi)者取走之后將導(dǎo)致消費(fèi)者線程阻塞。
public class Producer implements Runnable{ protected BlockingQueue queue = null; public Producer(BlockingQueue queue) { this.queue = queue; } public void run() { try { queue.put("1"); Thread.sleep(10000); queue.put("2"); Thread.sleep(10000); queue.put("3"); } catch (InterruptedException e) { e.printStackTrace(); } } }
下面的代碼是消費(fèi)者類Consumer
,它從隊列中獲取待處理的元素對象,并調(diào)用System.out
將其打印出來。
public class Consumer implements Runnable{ protected BlockingQueue queue = null; public Consumer(BlockingQueue queue) { this.queue = queue; } public void run() { try { System.out.println(queue.take()); System.out.println(queue.take()); System.out.println(queue.take()); } catch (InterruptedException e) { e.printStackTrace(); } } }
上面的代碼打印結(jié)果是每隔10秒打印一次,因?yàn)槠渲?code>take()方法在隊列內(nèi)沒有元素可以取到的時候,會阻塞當(dāng)前的消費(fèi)者線程,讓其處于等待狀態(tài),這個方法我們在上一節(jié)介紹BlockingQueue
的時候就已經(jīng)進(jìn)行過說明。
以上就是java并發(fā)編程工具類JUC之ArrayBlockingQueue的詳細(xì)內(nèi)容,更多關(guān)于java并發(fā)編程工具類ArrayBlockingQueue的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺析SpringBoot多數(shù)據(jù)源實(shí)現(xiàn)方案
現(xiàn)在很多項(xiàng)目的開發(fā)過程中,可能涉及到多個數(shù)據(jù)源,像讀寫分離的場景,或者因?yàn)闃I(yè)務(wù)復(fù)雜,導(dǎo)致不同的業(yè)務(wù)部署在不同的數(shù)據(jù)庫上,那么這樣的場景,我們應(yīng)該如何在代碼中簡潔方便的切換數(shù)據(jù)源呢,本文介紹SpringBoot多數(shù)據(jù)源實(shí)現(xiàn)方案,感興趣的朋友跟隨小編一起看看吧2024-02-02hibernate-validator如何使用校驗(yàn)框架
高效、合理的使用hibernate-validator校驗(yàn)框架可以提高程序的可讀性,以及減少不必要的代碼邏輯,本文主要介紹了hibernate-validator如何使用校驗(yàn)框架,感興趣的可以了解一下2022-04-04