有界阻塞队列ArrayBlockingQueue和无界阻塞队列LinkedBlockingQueue
ArrayBlockingQueue和LinkedBlockingQueue最大的區(qū)別是一個(gè)是有界無界,各有優(yōu)劣。
先看實(shí)例代碼:
main函數(shù)起2個(gè)線程模擬生成消費(fèi)者
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;public class BlockingQueueExample {public static void main(String[] args) throws Exception {BlockingQueue queue = new ArrayBlockingQueue(1024);//BlockingQueue queue = new LinkedBlockingQueue(1024);Producer producer = new Producer(queue);Consumer consumer = new Consumer(queue);new Thread(producer).start();new Thread(consumer).start();Thread.sleep(4000);}
}
生產(chǎn)者:?
public class Producer implements Runnable{protected BlockingQueue queue = null;public Producer(BlockingQueue queue) {this.queue = queue;}public void run() {try {queue.put("1>>> "+DateUtil.getNowTimeString());Thread.sleep(1000);queue.put("2>>> "+DateUtil.getNowTimeString());Thread.sleep(5000);queue.put("3>>> "+DateUtil.getNowTimeString());} catch (InterruptedException e) {e.printStackTrace();}}
}
消費(fè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()+" "+DateUtil.getNowTimeString());System.out.println(queue.take()+" "+DateUtil.getNowTimeString());System.out.println(queue.take()+" "+DateUtil.getNowTimeString());} catch (InterruptedException e) {e.printStackTrace();}}
}
數(shù)據(jù)量少的情況下LinkedBlockingQueue差別不大。
?
二者的類圖:
LinkedBlockingQueue源碼初始化默認(rèn)不指定大小就使用Integer.MAX_VALUE配置的默認(rèn)值:
/*** Creates a {@code LinkedBlockingQueue} with a capacity of* {@link Integer#MAX_VALUE}.*/public LinkedBlockingQueue() {this(Integer.MAX_VALUE);}
LinkedBlockingQueue中的鎖是分離的,生產(chǎn)者的鎖putLock,消費(fèi)者的鎖takeLock?
?ArrayBlockingQueue生產(chǎn)者和消費(fèi)者使用的是同一把鎖ReentrantLock lock:
put:?
take:?
https://stackoverflow.com/questions/18375334/what-is-the-difference-between-arrayblockingqueue-and-linkedblockingqueue
https://stackoverflow.com/questions/35967792/when-to-prefer-linkedblockingqueue-over-arrayblockingqueue
?
關(guān)于二者的異同參考下面的這個(gè)總結(jié)的還不錯(cuò):LinkedBlockingQueue和ArrayBlockingQueue的異同
相同:
LinkedBlockingQueue和ArrayBlockingQueue都是可阻塞的隊(duì)列
內(nèi)部都是使用ReentrantLock和Condition來保證生產(chǎn)和消費(fèi)的同步;
當(dāng)隊(duì)列為空,消費(fèi)者線程被阻塞;當(dāng)隊(duì)列裝滿,生產(chǎn)者線程被阻塞;
使用Condition的方法來同步和通信:await()和signal()
不同:
1、鎖機(jī)制不同
LinkedBlockingQueue中的鎖是分離的,生產(chǎn)者的鎖PutLock,消費(fèi)者的鎖takeLock
而ArrayBlockingQueue生產(chǎn)者和消費(fèi)者使用的是同一把鎖;
2、底層實(shí)現(xiàn)機(jī)制也不同
LinkedBlockingQueue內(nèi)部維護(hù)的是一個(gè)鏈表結(jié)構(gòu)。
在生產(chǎn)和消費(fèi)的時(shí)候,需要?jiǎng)?chuàng)建Node對(duì)象進(jìn)行插入或移除,大批量數(shù)據(jù)的系統(tǒng)中,其對(duì)于GC的壓力會(huì)比較大。
而ArrayBlockingQueue內(nèi)部維護(hù)了一個(gè)數(shù)組
在生產(chǎn)和消費(fèi)的時(shí)候,是直接將枚舉對(duì)象插入或移除的,不會(huì)產(chǎn)生或銷毀任何額外的對(duì)象實(shí)例。
3、構(gòu)造時(shí)候的區(qū)別
LinkedBlockingQueue有默認(rèn)的容量大小為:Integer.MAX_VALUE,當(dāng)然也可以傳入指定的容量大小
ArrayBlockingQueue在初始化的時(shí)候,必須傳入一個(gè)容量大小的值
4、執(zhí)行clear()方法
LinkedBlockingQueue執(zhí)行clear方法時(shí),會(huì)加上兩把鎖
?5、統(tǒng)計(jì)元素的個(gè)數(shù)
LinkedBlockingQueue中使用了一個(gè)AtomicInteger對(duì)象來統(tǒng)計(jì)元素的個(gè)數(shù),ArrayBlockingQueue則使用int類型來統(tǒng)計(jì)元素。
?
這個(gè)博客寫的并發(fā)編程內(nèi)容很全可以看看:http://tutorials.jenkov.com/java-concurrency/blocking-queues.html?
這個(gè)圖畫的很細(xì),如果前面看不明白可以看看這個(gè):深入剖析java并發(fā)之阻塞隊(duì)列LinkedBlockingQueue與ArrayBlockingQueue
?
總結(jié)
以上是生活随笔為你收集整理的有界阻塞队列ArrayBlockingQueue和无界阻塞队列LinkedBlockingQueue的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一句话说清聚集索引和非聚集索引以及MyS
- 下一篇: 泰拉瑞亚被折磨的灵魂怎么找?