ArrayBlockingQueue和LinkedBlockingQueue的區(qū)別:
隊列中鎖的實現(xiàn)不同
ArrayBlockingQueue實現(xiàn)的隊列中的鎖是沒有分離的巩步,即生產(chǎn)和消費用的是同一個鎖;
LinkedBlockingQueue實現(xiàn)的隊列中的鎖是分離的,即生產(chǎn)用的是putLock羹膳,消費是takeLock在生產(chǎn)或消費時操作不同
ArrayBlockingQueue實現(xiàn)的隊列中在生產(chǎn)和消費的時候老客,是直接將枚舉對象插入或移除的牍颈;
LinkedBlockingQueue實現(xiàn)的隊列中在生產(chǎn)和消費的時候,需要把枚舉對象轉(zhuǎn)換為Node<E>進行插入或移除沽瘦,會影響性能隊列大小初始化方式不同
ArrayBlockingQueue實現(xiàn)的隊列中必須指定隊列的大小农尖;
LinkedBlockingQueue實現(xiàn)的隊列中可以不指定隊列的大小析恋,但是默認是Integer.MAX_VALUE
4.ArrayBlockingQueue采用的是數(shù)組,LinkedBlockingQueue采用的是單向鏈表
put take 實現(xiàn)原理:
里面有兩個顯式條件隊列Condition 由ReentrantLock newConditon()得到
一個為notFull:沒有滿
另一個為notEmpty:不是空的
final Object[] items;緩沖隊列
當put一個元素時先判斷是不是滿的如果是九調(diào)用notFull.await()阻塞到不是滿的
添加成功之后調(diào)用notEmpty.singnal();通知消費者有產(chǎn)品可消費了盛卡,解除消費者阻塞
當take一個元素時先判斷是不是空的如果是空的先調(diào)用notEmpty.await()阻塞助隧,如果取得了元素(從items里面移除),就調(diào)用notFull.singnal()喚醒并阻塞的生產(chǎn)者滑沧。
一些主要方法
offer
將元素插入隊列并村,成功返回true,如果當前沒有可用的空間滓技,則返回false
offer(E e, long timeout, TimeUnit unit)
將元素插入隊列哩牍,在到達指定的等待時間前等待可用的空間
E poll(long timeout, TimeUnit unit)
獲取并移除隊列的頭部,在指定的等待時間前等待可用的元素
E poll()
沒有的話返回null
void put(E e)
將元素插入隊列令漂,將等待可用的空間(堵塞)
take()
獲取并移除隊列的頭部膝昆,在元素變得可用之前一直等待(堵塞)
code
public static void main(String[] args){
//LinkedBlockingQueue<E>
BlockingQueue queue=new ArrayBlockingQueue(3);
for(int i=0;i<2;i++){
new Thread(){
public void run(){
while(true){
try{
Thread.sleep((long)Math.random()*1000);
System.out.println(Thread.currentThread().getName()+"準備放數(shù)據(jù)");
queue.put(1);
System.out.println(Thread.currentThread().getName()+"放了數(shù)據(jù)丸边,隊列目前有"+queue.size()+"個數(shù)據(jù)");
}
catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
}
new Thread(){
public void run(){
while(true){
try{
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"準備取數(shù)據(jù)");
queue.take();
System.out.println(Thread.currentThread().getName()+"取走一個數(shù)據(jù),隊列目前有"+queue.size()+"個數(shù)據(jù)");
}
catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
}
運行結(jié)果: