接ArrayBlockingQueue,這里我談下我對LinkedBlockingQueue的理解。
由阻塞隊列的ArrayBlockingQueue和LinkedBlockingQueue乾吻,我們很容易聯(lián)想到List的兩種實現(xiàn):ArrayList和LinkedList旋恼。ArrayList與ArrayBlockingQueue相似,底層都使用了數(shù)組圈暗,同樣LinkedList和LinkedBlockingQueue也類似粥鞋,底層使用了鏈表缘挽。不過這里的鏈表還是有些許不同的:
1. LinkedList使用了雙向鏈表,而LinkedBlockingQueue使用了單向鏈表呻粹。
2. LinkedList的容量理論上是無限的壕曼,而LinkedBlockingQueue卻是有限的。
讓我們來看看構(gòu)造函數(shù):
無參構(gòu)造函數(shù)實際上創(chuàng)建了一個大小為Integer.MAX_VALUE等浊,而有參構(gòu)造函數(shù)傳入的也是int腮郊。也就是說其實LinkedBlockingQueue是有界的。
接下來筹燕,我們看看它所使用的鎖轧飞。
從代碼中可以看出,它有兩個鎖撒踪,一個takeLock(讀鎖)过咬,一個putLock(寫鎖)。這與ArrayBlockingQueue是不一樣的糠涛。ArrayBlockingQueue只有一個鎖援奢。為什么有這樣的差異呢兼犯?ArrayBlockingQueue底層使用了數(shù)組忍捡,存儲空間是連續(xù)的,讀寫同一片存儲空間切黔,而且可能涉及到元素的移動砸脊,只能用同一把鎖來控制訪問,而LinkedBlockingQueue使用的是鏈表纬霞,存儲空間是不連續(xù)的凌埂,元素的異動只是指針的變更,讀寫鎖自然可以分離诗芜。
兩個Condition分別使用在不同場景下:
notEmpty和takeLock搭配瞳抓,獲取了takeLock還不夠,還必須滿足notEmpty的條件伏恐。
notFull和putLock搭配孩哑,獲取了putLock還不夠,還必須滿足notFull的條件翠桦。
再來看看put方法横蜒。
代碼比較簡單明了,只說三點:
1. 不允許Null值存入鏈表。
2. 入隊enqueue方法有兩步丛晌,第一仅炊,把尾指針的next指向新加入的Node,第二澎蛛,把尾指針重新指向新加入的Node抚垄。這個方法是線程安全的,因為它是在獲得lock后執(zhí)行的
3. 局部變量c是從-1開始的谋逻,代表元素還沒有成功設置督勺。
類似的,我們也可以分析take方法斤贰,這里就不在贅述智哀。可以稍微看下出隊的方法荧恍。
首先瓷叫,把頭結(jié)點的next指向自己,這樣就沒有GC Roots可達了送巡,接著把第一個節(jié)點元素置空摹菠,好騰出來做頭結(jié)點。最后返回置空前的元素值骗爆。
LinkedBlockingQueue就分析到這里次氨。