(五)java 執行緒池工作佇列
阿新 • • 發佈:2018-12-23
執行緒池工作佇列
上一章我們介紹了執行緒的基本情況,這一章進一步瞭解執行緒池中的工作佇列,BlockingQueue
佇列。
在類 Executors
中,我們可以看到不同執行緒池維護的工作佇列是不同的,如newCachedThreadPool
使用的是SynchronousQueue
同步佇列,newSingleThreadScheduledExecutor
使用DelayedWorkQueue
,
newFixedThreadPool
和newScheduledThreadPool
使用LinkedBlockingQueue
。它們都是實現了併發包java.util.concurrent
BlockingQueue
,下面說說這個介面。
BlockingQueue 阻塞佇列
繼承於佇列 Queue
,遵循先進先出原則(FIFO),佇列提供幾種基本的操作,新增元素(隊尾)、移除元素(隊頭)、取出隊頭元素(不移除),每種操作都有兩個方法,一種有可能拋異常,一種返回操作成功或失敗。
在這個基礎上,阻塞佇列增加了操作鎖,保證了資料安全,當然這個具體實現是在子類中完成,介面僅僅描述方法的特點,還增加兩種不同的操作實現。下面描述這四種不同型別的操作:
- 操作,可能拋異常
- 操作,不拋異常(特殊如類轉換異常、空指標、引數異常不屬於,僅當佇列已滿不會跑狀態異常)
- 無限期阻塞執行緒直至操作成功
- 有時間限制的操作
新增 | 移除 | 檢查 |
---|---|---|
add(e) | remove(o) | element() |
offer(e) | poll() | peek() |
put(e) | take() | \ |
offer(e,time,unit) | poll(time,unit) | \ |
以及增加了拷貝 drainTo
,如執行緒池的 shutdownNow
contains
,剩餘容量查詢remainingCapacity
等。
實現的子類
- ArrayBlockingQueue 陣列型阻塞佇列
- LinkedBlockingQueue 連結串列型阻塞佇列
- DelayQueue 延時佇列
- SynchronousQueue 同步佇列
- PriorityBlockingQueue 優先阻塞佇列
ArrayBlockingQueue
特點:
- 初始化一定容量的陣列
- 使用一個重入鎖,預設使用非公平鎖,入隊和出隊共用一個鎖,互斥
- 是有界設計,如果容量滿無法繼續新增元素直至有元素被移除
- 使用時開闢一段連續的記憶體,如果初始化容量過大容易造成資源浪費,過小易新增失敗
LinkedBlockingQueue
特點:
- 內部使用節點關聯,會產生多一點記憶體佔用
- 使用兩個重入鎖分別控制元素的入隊和出隊,用
Condition
進行執行緒間的喚醒和等待 - 有邊界的,在預設構造方法中容量是
Integer.MAX_VALUE
- 非連續性記憶體空間
- 使用兩個重入鎖分別控制元素的入隊和出隊,用
DelayQueue
特點:
- 無邊界設計
- 新增(put)不阻塞,移除阻塞
- 元素都有一個過期時間
- 取元素只有過期的才會被取出
SynchronousQueue
特點:
- 內部容量是0
- 每次刪除操作都要等待插入操作
- 每次插入操作都要等待刪除操作
- 一個元素,一旦有了插入執行緒和移除執行緒,那麼很快由插入執行緒移交給移除執行緒,這個容器相當於通道,本身不儲存元素
- 在多工佇列,是最快的處理任務方式。
PriorityBlockingQueue
特點:
- 無邊界設計,但容量實際是依靠系統資源影響
- 新增元素,如果超過1,則進入優先順序排序