1. 程式人生 > >執行緒有關的方法或類

執行緒有關的方法或類

  • ConcurrentHashMap:
  • CopyOnWriteArrayList:用於在遍歷操作為主要操作的情況下代替同步的List。
  • PriorityQueue:一個(非併發的)優先佇列(要併發的話,使用PriorityBlockingQueue)。PriorityQueue是基於優先堆的一個無界佇列,這個優先佇列中的元素可以預設自然排序或者通過提供的Comparator(比較器)在佇列例項化的時排序。比方說我們有一個每日交易時段生成股票報告的應用程式,需要處理大量資料並且花費很多處理時間。客戶向這個應用程式傳送請求時,實際上就進入了佇列。我們需要首先處理優先客戶再處理普通使用者。在這種情況下,Java的PriorityQueue(優先佇列)會很有幫助。參考:
    Java優先佇列(PriorityQueue)示例
  • BlockingQueue:增加了阻塞的插入和獲取等操作。這個介面有很多插入和移除方法,當沒有空間可以用或者空間已滿時下面各個方法的處理方式不一樣。參看:BlockingQueue API
  • ConcurrentLinkedQueue:一個可以併發的先進先出佇列。它的size()方法非常慢,是從頭到尾遍歷一遍集合。而LinkedBlockingQueue的size()方法則是從一個變數裡取值,速度快。它和LinkedBlockingQueue不同的重要一點就是,它不是阻塞的,而LinkedBlockingQueue是阻塞的。
  • LinkedBlockingQueue:與LinkedList類似,但比同步List擁有更好的併發效能。可以指定容量,也可以不指定,不指定的話,預設最大是Integer.MAX_VALUE。內部使用鎖的個數是2個(生產者一個,消費者一個)。如果沒有其它特殊需求,是生產者-消費者模式的首選。關於LinkedBlockingQueue、ArrayBlockingQueue、SynchronousQueue和ConcurrentLinkedHashMap效能比較,請看下面的文章:
  • ArrayBlockingQueue:與ArrayList類似,但比同步List擁有更好的併發效能。是一個有界快取的等待佇列。在生產者放入資料和消費者獲取資料,都是共用同一個鎖物件。
  • SynchronousQueue:實際上它不是一個真正的佇列(是一種無緩衝的等待佇列),因為它不會為佇列中的元素維護儲存空間,它維護一組執行緒,這些執行緒在等待著把元素加入或移出佇列。但是由於該Queue本身的特性,在某次新增元素後必須等待其他執行緒取走後才能繼續新增;可以認為SynchronousQueue是一個快取值為1的阻塞佇列,但是 isEmpty()方法永遠返回是true,remainingCapacity() 方法永遠返回是0,remove()和removeAll() 方法永遠返回是false,iterator()方法永遠返回空,peek()方法永遠返回null。
    SynchronousQueue經常用來,一端或者雙端嚴格遵守”單工”(單工作者)模式的場景,佇列的兩個操作端分別是productor和consumer.常用於一個productor多個consumer的場景。
    在ThreadPoolExecutor中,通過Executors建立的cachedThreadPool就是使用此型別佇列.已確保,如果現有執行緒無法接收任務(offer失敗),將會建立新的執行緒來執行.
  • ConcurrentSkipListMap:作為同步的TreeMap的併發替代品。在非多執行緒的情況下,應當儘量使用TreeMap。此外對於併發性相對較低的並行程式可以使用Collections.synchronizedSortedMap將TreeMap進行包裝,也可以提供較好的效率。對於高併發程式,應當使用ConcurrentSkipListMap,能夠提供更高的併發度。參考:
  • ConcurrentSkipListSet:作為同步的TreeSet的併發替代品。它是通過ConcurrentSkipListMap實現的。
  • LinkedTransferQueue:BlockingQueue(和Queue)是Java 5中加入的介面,它是指這樣的一個佇列:當生產者向佇列新增元素但佇列已滿時,生產者會被阻塞;當消費者從佇列移除元素但佇列為空時,消費者會被阻塞。TransferQueue則更進一步,生產者會一直阻塞直到所新增到佇列的元素被某一個消費者所消費(不僅僅是新增到佇列裡就完事,例如:BlockingQueue)。通過它被用來執行緒之間傳遞訊息,如果它的佇列容量設定成0的話,功能就像SynchronousQueue一樣。
    Doug Lea說從功能角度來講,LinkedTransferQueue實際上是ConcurrentLinkedQueue、SynchronousQueue(公平模式)和LinkedBlockingQueue的超集。而且LinkedTransferQueue更好用,因為它不僅僅綜合了這幾個類的功能,同時也提供了更高效的實現。而且還保持了記憶體的可見性。
    參考:
  • Deque:此介面定義在雙端佇列兩端訪問元素的方法。與 List 介面不同,此介面不支援通過索引訪問元素。參考:Java 資料結構之Deque(雙向佇列)
  • CountDownLatch:CountDownLatch是一個同步輔助類,在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待。參考:Java多執行緒系列–“JUC鎖”09之 CountDownLatch原理和示例
  • Semaphore:Semaphore是一個計數訊號量,它的本質是一個”共享鎖”。訊號量維護了一個訊號量許可集。執行緒可以通過呼叫acquire()來獲取訊號量的許可;當訊號量中有可用的許可時,執行緒能獲取該許可;否則執行緒必須等待,直到有可用的許可為止。 執行緒可以通過release()來釋放它所持有的訊號量許可。參考:Java多執行緒系列–“JUC鎖”11之 Semaphore訊號量的原理和示例
  • CyclicBarrier:CyclicBarrier是一個同步輔助類,允許一組執行緒互相等待,直到到達某個公共屏障點 (common barrier point)。因為該 barrier 在釋放等待執行緒後可以重用,所以稱它為迴圈 的 barrier。參考:Java多執行緒系列–“JUC鎖”10之 CyclicBarrier原理和示例
  • ReentrantLock:是一個可重入的互斥鎖,又被稱為“獨佔鎖”。ReentrantLock分為“公平鎖”和“非公平鎖”。它們的區別體現在獲取鎖的機制上是否公平。“鎖”是為了保護競爭資源,防止多個執行緒同時操作執行緒而出錯,ReentrantLock在同一個時間點只能被一個執行緒獲取(當某執行緒獲取到“鎖”時,其它執行緒就必須等待)。參考:Java多執行緒系列–“JUC鎖”02之 互斥鎖ReentrantLock
  • Condition:主要是為了代替Object 監視器方法(wait、notify 和 notifyAll)。Condition 將 Object 監視器方法(wait、notify 和 notifyAll)分解成截然不同的物件,以便通過將這些物件與任意 Lock 實現組合使用,為每個物件提供多個等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監視器方法的使用。參考:JUC的Condition注意事項
  • ReentrantReadWriteLock:比如說對一個檔案進行操作,對於寫操作必須要用到互斥鎖來保證資料唯一性,但是當讀的時候呢,如果允許同時並行多個讀操作,那將大大提高效率,只要保證所有的讀操作與寫操作之間互斥就可以了,讀操作之間是可以共享的。
    在ReentrantReadWriteLock中,有公平和非公平兩種模式:在非公平模式下:當一個鎖釋放了,不能確定到底是writer等待執行緒獲得寫鎖,還是readr等待執行緒們獲得讀鎖;在公平模式下:一個鎖釋放了,選擇等待最久的一個(組)執行緒獲得鎖,無論是writer執行緒還是reader執行緒們。參考:ReentrantReadWriteLock讀寫鎖的使用
  • LockSupport:LockSupport很類似於二元訊號量(只有1個許可證可供使用),如果這個許可還沒有被佔用,當前執行緒獲取許可並繼續執行;如果許可已經被佔用,當前執行緒阻塞,等待獲取許可。LockSupport是不可重入的。參考:LockSupport的park和unpark的基本使用,以及對執行緒中斷的響應性
  • CompletionService:而CompletionService的實現是維護一個儲存Future物件的BlockingQueue。只有當這個Future物件狀態是結束的時候,才會加入到這個Queue中,take()方法其實就是Producer-Consumer中的Consumer。它會從Queue中取出Future物件,如果Queue是空的,就會阻塞在那裡,直到有完成的Future物件加入到Queue中。所以,先完成的必定先被取出。這樣就減少了不必要的等待時間。