摘要:懶漢單例模式怎么變得線程安全?Master-Worker歸并模式,工作竊取算法。Java線程相關源碼使用了什么設計模式?
資料引用:《Java高并發核心編程·卷2》
目錄
線程安全的單例模式
Master-Worker模式
工作竊取算法
并發總結
線程篇歸納
Thread
JUC
異步
代碼質量
模式總結
線程安全的單例模式
懶漢模式,即調用才創建的單例模式在高并發情況下,會有多個單例的情況。
解決方案-雙重校驗+volatile:
檢查是否已經創建——>加鎖創建過程——>創建前判斷是否已經創建
第二次檢查主要是防止其他線程已經通過第一次檢查等待獲取鎖。
volatile關鍵字禁止實例創建過程中的指令重排。
/*** 雙重檢查鎖,解決多線程可能出現的多實例問題*/
public class SingleTon2 {private static volatile SingleTon2 singleton;private SingleTon2() {}public static SingleTon2 getInstance() {if (singleton == null) {synchronized (SingleTon2.class) {if (singleton == null) {singleton = new SingleTon2();}}}return singleton;}//類中其他方法,盡量是staticpublic static void doSomething() {System.out.println("doSomething");}
}
Master-Worker模式
一種歸并類型的模式。
任務的調度和執行分離,調度角色為Master,執行任務的角色為Worker,Master負責接收、分配任務和合并(Merge)結果,Woker執行任務。
Master-Worker 這種模式適合小規模任務分發。
大規模調度需另外設計如:事件驅動+MapReduce,去中心化、實時性、規模化處理更接近現代分布式架構。其設計目標是高效處理海量并發請求,保證準確性和一致性,而非簡單依賴單一Master協調。
工作竊取算法
工作竊取算法的核心思想是:工作線程自己的活干完了之后,會去看看別人有沒有沒干完的活,如果有就拿過來幫忙干。工作竊取算法的主要邏輯:每個線程擁有一個雙端隊列(本地隊列),用于存放需要執行的任務,當自己的隊列沒有任務時,可以從其他線程的任務隊列中獲得一個任務繼續執行。

并發總結
對于并發、分布式來說,線程\節點之間的同步是有明顯開銷的,應該用盡可能少的同步做到相同的效果。
原則:
- 無鎖優先:用CAS(如AtomicInteger)或無共享數據替代鎖。
- 局部化:線程/節點盡量獨立計算,減少交互。
- 異步化:用事件驅動或消息隊列(如Kafka)解耦同步依賴。
- 最終一致性:分布式場景下,犧牲強一致性換取性能(如BASE模型)。
線程篇歸納
Thread
Java從線程的設計開始,除了設計有線程通用結構——線程ID、名稱、狀態、優先級,也為線程安全與線程狀態流轉做了設計。
且使用數字+枚舉類轉換的方式,減少了線程實例對象本身的運行開銷。
對于線程狀態的操縱,提供了不同的方法進行,對于阻塞狀態,加重入鎖。
對于線城池,Java將工作線程封裝成Worker對象,并使用HashSet來存儲工作線程,BlockingQueue來作為工作任務隊列,且很好地使用了隊列的阻塞方法來實現核心線程的不被清除。
JUC
JUC為了保證線程的原子性、可見性、有序性,大量使用CAS操作與volatile關鍵字。
能使用CAS的場景都使用了CAS,無鎖優先,又針對CAS的問題,先后迭代有“熱點分離”、“隊列削峰”的設計來減少CAS自旋帶來的性能損失。
對于CAS+volatile+版本號保證原子性、可見性、解決ABA問題,Java也設計有對應原子類如AtomicStampedReference等,使用的版本號為別的int類型與boolean類型。
異步
JUC異步模式有Master-Worker的歸并模式,ForkJoin的異步使用“工作竊取算法”來提速分治后的任務處理速度。
代碼質量
在線程相關的Java代碼中,可以看到Java源碼設計的非常嚴謹優雅,以線程池為例,基本設置為volatile保證可見性,對于沒有設置volatile的屬性,其僅在鎖范圍內使用。
又以CAS自旋為例,基本使用for(;;)的形式進行自旋。
體現了Java本身繼承、封裝、多態特性。以線程創建方式為例,體現有適配器與策略模式、模板方法等
高內聚、低耦合,且兼顧靈活與性能。
模式總結
Thread:
適配器(適配Runnable)
模板方法(run()定制)
JUC:
單例、工廠(線程池創建)
策略(拒絕策略)
裝飾器(FutureTask)
觀察者(CompletableFuture)
代理(ExecutorService)
狀態(線程池狀態)
建造者(復雜配置)
工作竊取(ForkJoinPool)
讀寫鎖(ReentrantReadWriteLock)