天天看點

Java 并發工具包 | J.U.C

Java 并發工具包 | J.U.C

不知道大家還有沒有印象,上次我們已經說過了,我們為了實作集合相關類的線程安全,JDK 提供了一套同步容器,也就是 Vector,Hashtable,還有一個 Collections 工具類中的幾個方法。

問題是什麼呢,同步容器并不能保證線程安全,我在們寫代碼的時候還需要注意一些方法的使用,在 JDK 1.5 及以後就出現了 java.util.current 包,這個包中就提供了大量的類來實作線程安全,這也就是我們經常說的 JUC。

舉例例子吧,與 HashMap 對應的線程安全的容器,ConcurrentHashMap 就是出自這個包。

稍微整理了一下這個包中都包含了哪些功能,做個思維導圖。

Java 并發工具包 | J.U.C

不得不說,這其中的知識點非常多,我這隻是列出了一部分,作為大綱,我呢也不可能都說,用到的類也很少,目前工作基本接觸不到這些類的使用。

但是吧,我還是強烈建議有基礎的同學看看源碼,膜拜一下大神。

我就簡單說幾個面試常問的,并發容器,atomic 包,Lock 和其實作類,線程池。

并發容器最最常問的就是 ConcurrentHashMap 的原理,四個字分段加鎖。使用的是 synchronized 代碼塊加鎖,隻不過鎖的範圍不再是整個 table ,而是一個一個的 Node。

原子包中的原子類主要就是提供了一些不需要加鎖就能保證原子性操作的一些方法,我們不使用鎖進行同步,而是使用算法來保證操作的原子性,主要涉及的算法是 CAS,核心方法就是 compareAndSwap。這個方法是實作是 native 的,嗯,不是 Java 實作的。

算法思想就是我拿工作記憶體中的值和主存中的值進行比較,若是一樣我才操作,不一樣那就修改主存中的值,繼續比較直到滿足條件。這樣做也就保證了主記憶體和工作記憶體中的值一緻。

有個有趣的事情,CAS 是定義在一個 Unsafe 類中的。有麼有想過,盡然還有這麼有意思的類名,原來這個類是由 sun 公司提供的,之是以命名為 Unsafe 是因為 GC 的時候不能回收這個類,是以官方不建議使用。

嗯,在 CAS 算法中還有可能出現 ABA 問題,就是說在讀取記憶體中變量的時候看起來沒有變化,可能是已經又變回來了,解決的方法就是每次修改變量的時候都會加上一個版本号,同時比較版本号和變量的值是否改變。

ReentrantLock 名為可重入鎖,就是說一個線程在獲得一個鎖之後,再次擷取該鎖時,不需要重新等待擷取。ReentrantLock 又分為公平鎖和非公平鎖,公平鎖指的是嚴格按照先來先得的順序排隊等待去擷取鎖,而非公平鎖每次擷取鎖時,是先直接嘗試擷取鎖,擷取不到,再按照先來先得的順序排隊等待。

ReentrantReadWriteLock 可重入讀寫鎖,指的是沒有線程進行寫操作時,多個線程可同時進行讀操作,當有線程進行寫操作時,其它讀寫操作隻能等待。可以多線程一起讀但是一旦有寫就需要等着,有較好的并發行和吞吐量。

線程頻繁的建立和銷毀是很浪費資源的,是以我們就建立一個線程池用來保證有一部分線程始終處于待命狀态,來任務了可以立馬執行,這也是線程池的優點,提高資源的使用率,提高了請求響應的速度,而且我們還可以管理已經建立的線程。

線程池主要關注點線上程池建立的 7 個參數上,我們并發量很小的時候,待命的線程過多也是浪費大量的資源,是以關于性能調優,這些沒有定論,要根據自身的業務場景。

參數主要是線程池的大小,最大線程數,設定空閑時間,線程過多時使用何種阻塞隊列,建立線程的工廠是什麼,當阻塞隊列也滿了時,采用什麼政策來處理後續線程。

東西真的好多,我這隻是說了一丢丢,好多東西我隻是知道但是沒有用過,我是感覺脫離業務的技術意義不大,雖然學起來感覺很牛逼,但是用不到的我也就止步于此了,大家加油,至少拓展了我們的思路,再接觸時不會慫!

原文位址

https://www.cnblogs.com/YJK923/p/10529719.html