在并發(fā)編程中很常用的實用工具類。此包包括了幾個小的、已標準化的可擴展框架,以及一些提供有用功能的類,沒有這些類,這些功能會很難實現(xiàn)或實現(xiàn)起來冗長乏味。下面簡要描述主要的組件。另請參閱 locks 和 atomic 包。
接口
-
Executor是一個簡單的標準化接口,用于定義類似于線程的自定義子系統(tǒng),包括線程池、異步 IO 和輕量級任務框架。根據(jù)所使用的具體 Executor 類的不同,可能在新創(chuàng)建的線程中,現(xiàn)有的任務執(zhí)行線程中,或者調(diào)用 execute() 的線程中執(zhí)行任務,并且可能順序或并發(fā)執(zhí)行。 -
ExecutorService提供了多個完整的異步任務執(zhí)行框架。ExecutorService 管理任務的排隊和安排,并允許受控制的關閉。 -
ScheduledExecutorService子接口及相關的接口添加了對延遲的和定期任務執(zhí)行的支持。ExecutorService 提供了安排異步執(zhí)行的方法,可執(zhí)行由Callable表示的任何函數(shù),結果類似于Runnable。 -
Future返回函數(shù)的結果,允許確定執(zhí)行是否完成,并提供取消執(zhí)行的方法。 -
RunnableFuture是擁有 run 方法的 Future, run方法執(zhí)行時將設置其結果。
實現(xiàn)
類 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 提供可調(diào)的、靈活的線程池。Executors 類提供大多數(shù) Executor 的常見類型和配置的工廠方法,以及使用它們的幾種實用工具方法。其他基于 Executor 的實用工具包括具體類 FutureTask,它提供 Future 的常見可擴展實現(xiàn),以及 ExecutorCompletionService,它有助于協(xié)調(diào)對異步任務組的處理。
隊列
java.util.concurrent ConcurrentLinkedQueue 類提供了高效的、可伸縮的、線程安全的非阻塞 FIFO 隊列。java.util.concurrent 中的五個實現(xiàn)都支持擴展的 BlockingQueue 接口,該接口定義了 put 和 take 的阻塞版本: LinkedBlockingQueue、 ArrayBlockingQueue、 SynchronousQueue、 PriorityBlockingQueue 和 DelayQueue。這些不同的類覆蓋了生產(chǎn)者-使用者、消息傳遞、并行任務執(zhí)行和相關并發(fā)設計的大多數(shù)常見使用的上下文。 BlockingDeque 接口擴展 BlockingQueue,以支持 FIFO 和 LIFO(基于堆棧)操作。LinkedBlockingDeque 類提供一個實現(xiàn)。
計時
TimeUnit 類為指定和控制基于超時的操作提供了多重粒度(包括納秒級)。該包中的大多數(shù)類除了包含不確定的等待之外,還包含基于超時的操作。在使用超時的所有情況中,超時指定了在表明已超時前該方法應該等待的最少時間。在超時發(fā)生后,實現(xiàn)會“盡力”檢測超時。但是,在檢測超時與超時之后再次實際執(zhí)行線程之間可能要經(jīng)過不確定的時間。接受超時期參數(shù)的所有方法將小于等于 0 的值視為根本不會等待。要“永遠”等待,可以使用 Long.MAX_VALUE 值。
同步器
四個類可協(xié)助實現(xiàn)常見的專用同步語句。 Semaphore 是一個經(jīng)典的并發(fā)工具。 CountDownLatch 是一個極其簡單但又極其常用的實用工具,用于在保持給定數(shù)目的信號、事件或條件前阻塞執(zhí)行。 CyclicBarrier 是一個可重置的多路同步點,在某些并行編程風格中很有用。 Exchanger 允許兩個線程在 collection 點交換對象,它在多流水線設計中是有用的。
并發(fā) Collection
除隊列外,此包還提供了設計用于多線程上下文中的 Collection 實現(xiàn): ConcurrentHashMap、 ConcurrentSkipListMap、 ConcurrentSkipListSet、 CopyOnWriteArrayList 和CopyOnWriteArraySet。當期望許多線程訪問一個給定 collection 時, ConcurrentHashMap 通常優(yōu)于同步的 HashMap, ConcurrentSkipListMap 通常優(yōu)于同步的 TreeMap。當期望的讀數(shù)和遍歷遠遠大于列表的更新數(shù)時, CopyOnWriteArrayList 優(yōu)于同步的ArrayList。
此包中與某些類一起使用的“Concurrent”前綴;是一種簡寫,表明與類似的“同步”類有所不同。例如,java.util.Hashtable 和 Collections.synchronizedMap(new HashMap())是同步的,但 ConcurrentHashMap 則是“并發(fā)的”。并發(fā) collection 是線程安全的,但是不受單個排他鎖的管理。在 ConcurrentHashMap 這一特定情況下,它可以安全地允許進行任意數(shù)目的并發(fā)讀取,以及數(shù)目可調(diào)的并發(fā)寫入。需要通過單個鎖不允許對 collection 的所有訪問時,“同步”類是很有用的,其代價是較差的可伸縮性。在期望多個線程訪問公共 collection 的其他情況中,通?!安l(fā)”版本要更好一些。當 collection 是未共享的,或者僅保持其他鎖時 collection 是可訪問的情況下,非同步 collection 則要更好一些。
大多數(shù)并發(fā) Collection 實現(xiàn)(包括大多數(shù) Queue)與常規(guī)的 java.util 約定也不同,因為它們的迭代器提供了弱一致的,而不是快速失敗的遍歷。弱一致的迭代器是線程安全的,但是在迭代時沒有必要凍結 collection,所以它不一定反映自迭代器創(chuàng)建以來的所有更新。
內(nèi)存一致性屬性
只有寫入操作 happen-before 讀取操作時,才保證一個線程寫入的結果對另一個線程的讀取是可視的。 synchronized 和 volatile 構造 happen-before 關系, Thread.start() 和 Thread.join() 方法形成 happen-before 關系。尤其是:
- 線程中的每個操作 happen-before 稍后按程序順序傳入的該線程中的每個操作。
- 一個解除鎖監(jiān)視器的(synchronized 阻塞或方法退出)happen-before 相同監(jiān)視器的每個后續(xù)鎖(synchronized 阻塞或方法進入)。并且因為 happen-before 關系是可傳遞的,所以解除鎖定之前的線程的所有操作 happen-before 鎖定該監(jiān)視器的任何線程后續(xù)的所有操作。
- 寫入 volatile 字段 happen-before 每個后續(xù)讀取相同字段。volatile 字段的讀取和寫入與進入和退出監(jiān)視器具有相似的內(nèi)存一致性效果,但不 需要互斥鎖。
- 在線程上調(diào)用 start happen-before 已啟動的線程中的任何線程。
- 線程中的所有操作 happen-before 從該線程上的 join 成功返回的任何其他線程。
java.util.concurrent 中所有類的方法及其子包擴展了這些對更高級別同步的保證。尤其是:
- 線程中將一個對象放入任何并發(fā) collection 之前的操作 happen-before 從另一線程中的 collection 訪問或移除該元素的后續(xù)操作。
- 線程中向 Executor 提交 Runnable 之前的操作 happen-before 其執(zhí)行開始。同樣適用于向 ExecutorService 提交 Callables。
- 異步計算(由 Future 表示)所采取的操作 happen-before 通過另一線程中 Future.get() 獲取結果后續(xù)的操作。
- “釋放”同步儲存方法(如 Lock.unlock、Semaphore.release和CountDownLatch.countDown)之前的操作 happen-before 另一線程中相同同步儲存對象成功“獲取”方法(如 Lock.lock、Semaphore.acquire、Condition.await 和 CountDownLatch.await)的后續(xù)操作。
- 對于通過 Exchanger 成功交換對象的每個線程對,每個線程中 exchange() 之前的操作 happen-before 另一線程中對應 exchange() 后續(xù)的操作。
- 調(diào)用 CyclicBarrier.await 之前的操作 happen-before 屏障操作所執(zhí)行的操作,屏障操作所執(zhí)行的操作 happen-before 從另一線程中對應 await 成功返回的后續(xù)操作。