高併發編程系列:4大併發工具類的功能、原理、以及應用場景

編程語言 Java 火箭 技術 優知學院 2018-12-17
高併發編程系列:4大併發工具類的功能、原理、以及應用場景

通常我們所說的併發包也就是java.util.concurrent,集中了Java併發工具類和併發容器等,今天主要介紹Java併發編程的工具類,我們先從Java併發工具包談起。

併發工具包涵蓋:

高併發編程系列:4大併發工具類的功能、原理、以及應用場景

1.併發工具類

提供了比synchronized更加高級的各種同步結構:包括CountDownLatch、CyclicBarrier、Semaphore等,可以實現更加豐富的多線程操作。

2.併發容器

提供各種線程安全的容器:最常見的ConcurrentHashMap、有序的ConcurrentSkipListMap,實現線程安全的動態數組CopyOnWriteArrayList等。

3.併發隊列

各種BlockingQueue的實現:常用的ArrayBlockingQueue、SynchorousQueue或針對特定場景的PriorityBlockingQueue。

4.Executor框架

可以創建各種不同類型的線程池,調度任務運行等,絕大部分情況下,不再需要自己從頭實現線程池和任務調度器。

常用的併發容器

高併發編程系列:4大併發工具類的功能、原理、以及應用場景

1.ConcurrentHashMap

側重於Map放入或者獲取的速度,而不在乎順序

2.ConcurrentSkipListMap

在乎順序,需要對數據進行非常頻繁的修改

3.CopyOnWriteArrayList

任何修改操作,如add、set、remove,都會拷貝原數組,修改後替換原來的數組,通過這種防禦性的方式,實現另類的線程安全。

4.各種併發隊列的實現

如各種BlockedQueue實現,比較典型的ArrayBlockingQueue、SynchorousQueue。

詳情請看:高併發編程系列:併發容器的原理,7大併發容器詳解、及使用場景

高併發編程系列:4大併發工具類的功能、原理、以及應用場景

常用的併發工具類

高併發編程系列:4大併發工具類的功能、原理、以及應用場景

1.CountDownLatch

功能

CountDownLatch是一個同步的輔助類,允許一個或多個線程,等待其他一組線程完成操作,再繼續執行。

原理

  • CountDownLatch是通過一個計數器來實現的,計數器的初始值為需要等待線程的數量。

eg:CountDownLatch c = new CountDownLatch(10); // 等待線程的數量為10

  • 主線程調用CountDownLatch的await()方法會阻塞當前線程(即:主線程在閉鎖上等待),直到計數器的值為0。
  • 當一個工作線程完成了自己的任務後,調用CountDownLatch的countDown()方法,計數器的值就會減1。
  • 當計數器值為0時,說明所有的工作線程都執行完了,此時,在閉鎖上等待的主線程就可以恢復執行任務。

應用場景

倒數計時器

例如:一種典型的場景就是火箭發射。在火箭發射前,為了保證萬無一失,往往還要進行各項設備、儀器的檢查。 只有等所有檢查完畢後,引擎才能點火。這種場景就非常適合使用CountDownLatch。

它可以使得點火線程,等待所有檢查線程全部完工後,再執行

使用方式

static final CountDownLatch end = new CountDownLatch(10);
end.countDown();
end.await();

示意圖:

高併發編程系列:4大併發工具類的功能、原理、以及應用場景

2.CyclicBarrier

功能:

CyclicBarrier的字面意思是可循環使用(Cyclic)的屏障(Barrier)。它要做的事情是,讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,直到最後一個線程到達屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續運行。

和CountDownLatch相似,也是等待某些線程都做完以後再執行。

與CountDownLatch區別

在於這個計數器可以反覆使用。比如,假設我們將計數器設置為10。那麼湊齊第一批1 0個線程後,計數器就會歸零,然後接著湊齊下一批10個線程。

原理:

1)CyclicBarrier是通過一個計數器來實現的,計數器的初始值為需要等待線程的數量。eg:CyclicBarrier c = new CyclicBarrier(2); // 等待線程的數量為2

2)每個線程調用CyclicBarrier的await()方法,使自己進入等待狀態。

3)當所有的線程都調用了CyclicBarrier的await()方法後,所有的線程停止等待,繼續運行。

使用方式:

public CyclicBarrier(int parties, Runnable barrierAction) 
barrierAction就是當計數器一次計數完成後,系統會執行的動作
await()

示意圖:

高併發編程系列:4大併發工具類的功能、原理、以及應用場景

3.信號量Semaphore

功能:Java提供了經典信號量Semaphore的實現,它通過控制一定數量的許可(permit)的方式,來達到限制通用資源訪問的目的。例如:控制併發的線程數。

原理:

1)Semaphore是通過一個計數器(記錄許可證的數量)來實現的,計數器的初始值為需要等待線程的數量。

eg:Semaphore s = new Semaphore(10); // 線程最大的併發數為10

2)線程通過acquire()方法獲取許可證(計數器的值減1),只有獲取到許可證才可以繼續執行下去,否則阻塞當前線程。

3)線程通過release()方法歸還許可證(計數器的值加1)。

說明:使用tryAcquire()方法可以立即得到執行的結果:嘗試獲取一個許可證,若獲取成功,則立即返回true,若獲取失敗,則立即返回false。

應用場景:

Semaphore可以用於做流量控制,特別是公用資源有限的應用場景,比如數據庫連接。

舉一個場景:例如在車站、機場等出租車時,當很多空出租車就位時,為防止過度擁擠,調度員指揮排隊等待坐車的隊伍一次進來5個人上車,等這5個人坐車出發,再放進去下一批。這和Semaphore的工作原理有些類似。

4.交換者Exchanger

功能:Exchanger(交換者)是一個用於線程間協作的工具類。Exchanger用於進行線程間的數據交換。它提供一個同步點,在這個同步點兩個線程可以交換彼此的數據。這兩個線程通過exchange方法交換數據, 如果第一個線程先執行exchange方法,它會一直等待第二個線程也執行exchange,當兩個線程都到達同步點時,這兩個線程就可以交換數據,將本線程生產出來的數據傳遞給對方。

原理

1)線程A調用public V exchange(V dataA)方法,線程A到達同步點,並且在線程B到達同步點前一直等待。

2)線程B調用public V exchange(V dataB)方法,線程B到達同步點。

3)線程A與線程B都達到同步點時,線程將自己的數據傳遞給對方,兩個線程完成了數據的交換了。

Exchanger的應用場景

Exchanger可以用於校對工作的場景。


以上就是Java併發工具類的介紹,除了從編程的角度應對高併發,更多還需要從架構設計的層面來應對高併發場景,例如:Redis緩存、CDN、異步消息等,詳細的內容如下。

更多高併發架構設計專題

高併發編程系列:4大併發工具類的功能、原理、以及應用場景

資料獲取方式

關注+轉發後,私信關鍵詞 【高併發】即可獲取!

重要的話講兩遍,轉發、轉發後再發私信,才可以拿到哦!

高併發編程系列:4大併發工具類的功能、原理、以及應用場景

相關推薦

推薦中...