「JDK併發包基礎」工具類詳解

在寫併發代碼來提升性能時,會遵循某些最佳寫法,而不是隻用基礎的wait和notify來控制複雜的流程。

Java.util.concurrent 包是專為 Java併發編程而設計的包,它下有很多編寫好的工具,使用這些更高等的同步工具來編寫代碼,讓我們的程序可以不費力氣就得到優化。這些工具還在由一些優秀的工程師不斷優化和完善,我們不必重複造輪子:

「JDK併發包基礎」工具類詳解

這篇文章講述思維導圖的工具類部分:

  1. ReentrantLock
  2. Condition
  3. Semaphore
  4. ReentrantReadWriteLock
  5. CountDownLatch
  6. CyclicBarrrer

1.ReentrantLock

1.1可重入

單線程可以重複進入,但必須重複退出。

「JDK併發包基礎」工具類詳解

一個線程拿到幾個許可,就得釋放幾次,不然就造成線程等待,可在命令行查看等待的線程:jps -->jstack [ option ] pid

「JDK併發包基礎」工具類詳解

1.2可中斷

長期線程在鎖上等待問題,可以通過中斷來解決:

「JDK併發包基礎」工具類詳解

「JDK併發包基礎」工具類詳解

可在命令行查看死鎖:jps -->jstack [ option ] pid

「JDK併發包基礎」工具類詳解

1.3可限時

可限時也是一個避免永久等待構成死鎖的解決方法:

「JDK併發包基礎」工具類詳解

1.4公平鎖

先來的線程先得到鎖,如果先來的線程一直拿不到鎖,則會產生飢餓現象,公平鎖雖然不會產生飢餓現象,排隊會導致程序效率差。通過閱讀ReentrantLock的源碼發現:默認是非公平的,如果傳入true,則是公平鎖:

「JDK併發包基礎」工具類詳解

2.Condition

Condition與ReentrantLock的關係就類似於synchronized與Object.wait()/notify()。但是它與ReentrantLock結合使用,有await和signal與之對應.

利用Condition實現順序執行:

「JDK併發包基礎」工具類詳解

3.Semaphore

翻譯為信號量,允許多個線程進入臨界區。說白了就是一個廣義上的鎖,相當於共享鎖。比如信號量中我可以給它指定10個許可,每一個許可可以分配給若干個線程(當然一個線程也可以拿多個許可),拿到許可線程可以執行,如果許可分發完了,後面的線程就和鎖一樣去做等待。換句話說,當信號量等於1的時候,就相當於一把鎖。

比如早期做限流時,我們系統是8核cpu,設置同時請求任務為8個,超過8個,可以用信號量讓線程等待來加以控制:

4.ReentrantReadWriteLock

ReentrantReadWriteLock,首先要做的是與ReentrantLock劃清界限, 它和後者都是單獨的實現,彼此之間沒有繼承或實現的關係。讀寫鎖可以很好的提高程序效率,如果讀也加鎖的話,每次只有一個線程能訪問,不符合高併發程序設計。ReentrantLock和synchronized都屬於阻塞的並行,會把線程掛起,而ReadWriteLock屬於無等待的併發。

訪問情況:讀讀共享,讀寫互斥,寫寫互斥

「JDK併發包基礎」工具類詳解

「JDK併發包基礎」工具類詳解

5.CountDownLatch

實際開發中經常用於監聽某些初始化操作,等待初始化完成後,通知主線程繼續工作,它相當於一個柵欄

「JDK併發包基礎」工具類詳解

測試代碼:

「JDK併發包基礎」工具類詳解

6.CyclicBarrrer

倒數計時器。假設有一個場景:每個線程代表一個跑步運動員,當運動員都準備好後,才能一起出發,只要有一個人沒有準備好,大家都等待:

「JDK併發包基礎」工具類詳解

系列:

【JDK併發包基礎】線程池詳解

【JDK併發包基礎】併發容器詳解

【JDK併發包基礎】工具類詳解


分享到:


相關文章: