java并發(fā)編程工具類JUC之ArrayBlockingQueue
Java BlockingQueue接口java.util.concurrent.BlockingQueue表示一個(gè)可以存取元素,并且線程安全的隊(duì)列。換句話說(shuō),當(dāng)多線程同時(shí)從 JavaBlockingQueue中插入元素、獲取元素的時(shí)候,不會(huì)導(dǎo)致任何并發(fā)問(wèn)題(元素被插入多次、處理多次等問(wèn)題)。
從java BlockingQueue可以引申出一個(gè)概念:阻塞隊(duì)列,是指隊(duì)列本身可以阻塞線程向隊(duì)列里面插入元素,或者阻塞線程從隊(duì)列里面獲取元素。比如:當(dāng)一個(gè)線程嘗試去從一個(gè)空隊(duì)列里面獲取元素的時(shí)候,這個(gè)線程將被阻塞直到隊(duì)列內(nèi)元素?cái)?shù)量不再為空。當(dāng)然,線程是否會(huì)被阻塞取決于你調(diào)用什么方法從BlockingQueue獲取元素,有的方法會(huì)阻塞線程,有的方法會(huì)拋出異常等等,下文我們會(huì)詳細(xì)介紹。
類ArrayBlockingQueue是BlockingQueue接口的實(shí)現(xiàn)類,它是有界的阻塞隊(duì)列,內(nèi)部使用數(shù)組存儲(chǔ)隊(duì)列元素。這里的“有界”是指存儲(chǔ)容量存在上限,不能無(wú)限存儲(chǔ)元素。在同一時(shí)間內(nèi)存儲(chǔ)容量存在著一個(gè)上限值,這個(gè)上限制在初始實(shí)例化的時(shí)候指定,之后便不能修改了。
ArrayBlockingQueue內(nèi)部采用FIFO (First In, First Out)先進(jìn)先出的方法實(shí)現(xiàn)隊(duì)列數(shù)據(jù)的存取,隊(duì)首的元素是在隊(duì)列中保存時(shí)間最長(zhǎng)的元素對(duì)象,隊(duì)尾的元素是在隊(duì)列中保存時(shí)間最短的元素對(duì)象。
下面的代碼說(shuō)明如何初始化一個(gè)ArrayBlockingQueue,并向其中添加一個(gè)對(duì)象:
BlockingQueue queue = new ArrayBlockingQueue(1024);
queue.put("1"); //向隊(duì)列中添加元素
Object object = queue.take(); //從隊(duì)列中取出元素
BlockingQueue可以通過(guò)泛型來(lái)限定隊(duì)列中存儲(chǔ)數(shù)據(jù)的類型,下面的代碼以String為泛型,表示該隊(duì)列只能存儲(chǔ)String類型。
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1024);
queue.put("1");
String string = queue.take();
實(shí)現(xiàn)一個(gè)生產(chǎn)消費(fèi)的實(shí)例
在前面的文章中我們?cè)?jīng)講過(guò):BlockingQueue經(jīng)常被用于生產(chǎn)消費(fèi)的緩沖隊(duì)列。下面我們就使用ArrayBlockingQueue來(lái)真正的實(shí)現(xiàn)一個(gè)生產(chǎn)消費(fèi)的例子。
類BlockingQueueExample開(kāi)啟兩個(gè)獨(dú)立線程,一個(gè)是Producer生產(chǎn)者線程,負(fù)責(zé)向隊(duì)列中添加數(shù)據(jù);另一個(gè)是Consumer消費(fèi)者線程,負(fù)責(zé)從隊(duì)列中取出數(shù)據(jù)進(jìn)行處理。
public class BlockingQueueExample {
public static void main(String[] args) throws Exception {
//使用ArrayBlockingQueue初始化一個(gè)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(); //開(kāi)啟生產(chǎn)者線程
new Thread(consumer).start(); //開(kāi)啟消費(fèi)者線程
Thread.sleep(4000);
}
}
類Producer為生產(chǎn)者,每隔10秒鐘使用put()方法向隊(duì)列中放入一個(gè)對(duì)象,放入三次。在這10秒的間隔內(nèi),隊(duì)列數(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,它從隊(duì)列中獲取待處理的元素對(duì)象,并調(diào)用System.out將其打印出來(lái)。
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()方法在隊(duì)列內(nèi)沒(méi)有元素可以取到的時(shí)候,會(huì)阻塞當(dāng)前的消費(fèi)者線程,讓其處于等待狀態(tài),這個(gè)方法我們?cè)谏弦还?jié)介紹BlockingQueue的時(shí)候就已經(jīng)進(jìn)行過(guò)說(shuō)明。
以上就是java并發(fā)編程工具類JUC之ArrayBlockingQueue的詳細(xì)內(nèi)容,更多關(guān)于java并發(fā)編程工具類ArrayBlockingQueue的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springboot+dubbo+validation 進(jìn)行rpc參數(shù)校驗(yàn)的實(shí)現(xiàn)方法
這篇文章主要介紹了springboot+dubbo+validation 進(jìn)行rpc參數(shù)校驗(yàn)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Java調(diào)用ChatGPT的實(shí)現(xiàn)代碼
這篇文章主要介紹了Java調(diào)用ChatGPT的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02
95%的Java程序員人都用不好Synchronized詳解
這篇文章主要為大家介紹了95%的Java程序員人都用不好Synchronized詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
基于Java HttpClient和Htmlparser實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲(chóng)代碼
這篇文章主要介紹了基于Java HttpClient和Htmlparser實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲(chóng)代碼的相關(guān)資料,需要的朋友可以參考下2015-12-12
解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決
這篇文章主要介紹了解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
SpringBoot集成POI實(shí)現(xiàn)Excel導(dǎo)入導(dǎo)出的示例詳解
Apache?POI?是用Java編寫(xiě)的免費(fèi)開(kāi)源的跨平臺(tái)的?Java?API,Apache?POI提供API給Java程序?qū)icrosoft?Office格式檔案讀和寫(xiě)的功能。本文主要介紹通過(guò)SpringBoot集成POI工具實(shí)現(xiàn)Excel的導(dǎo)入和導(dǎo)出功能,需要的可以參考一下2022-07-07

