Java多執行緒收集

Java多執行緒小收集

工作中經常用到多執行緒而且多執行緒也非常重要,所以最近計劃深入研究並總結下多執行緒部分,本次先簡單的對多執行緒做個小結。

首先Java中關於多執行緒的幾個重要概念。

執行緒池概念:可以減少執行緒的建立和釋放,也可以合理利用CPU多核的效能。

鎖的概念: 防止資源衝突及保證原子操作。

佇列的概念: 將被阻塞的程序放入佇列中。

核心原理:

CAS:Compare And Swap 比較某記憶體位置預期值和新值 -> 底層Native方法 sun。misc。Unsafe -> 利用CPU的原子操作屬性實現。

AQS: AbstractQueueSynchronizer -> FIFO佇列(也叫CLH佇列), 多個執行緒採用競爭資源失敗後會放到一個列表中,頭Node是哨兵或啞節點,後續每個Node代表一個執行緒,每個節點維護一個等待線狀態waitStatus。當前如果無法獲取資源或interrupted。 等資源unlock後會觸發連結串列頭後的第一個元素去嘗試申請資源,如果申請成功就繼續執行。

主要有哪些類:

多執行緒類實現

Thread: 繼承Thread。

Runnable: 繼承Runnable並使用Thread來啟動

Calllable:繼承Callable。 利用ExecutorService來execute或submit執行。使用Thread啟動也可以。

BlockingQueue 系列: 底層利用ReentrantLock及Condition加鎖實現生產者消費者模型。

ArrayBlockingQueue: 底層資料結構: 陣列

LinkedBlockingQueue: 底層資料結構: 連結串列

DelayQueue: 底層資料結構: PriorityQueue(利用比較器排序)。

Concurrent 系列: 底層主要利用CAS來保證原子性操作

ConcurrentHashMap: 底層: (雜湊表 + 連結串列/紅黑樹) + CAS/Synchronized。

ConcurrentLinkedQueue及ConcurrentLinkedDeque:底層: 連結串列 + CAS

ConcurrentSkipListMap及ConcurrentSkipListSet:底層結構: Node + Index + HeadIndex 類似於B+數。

CopyOnWrite 系列: 底層用ReentrantLock加鎖,擴容複製並新增新的元素。

CopyOnWriteArrayList:

CopyOnWriteArraySet: 底層是CopyOnWriteArrayList實現。

執行緒同步機制

CountDownlatch:底層實現,定義資源數N, 使用AQS來控制多執行緒爭搶操作資源,利用CAS來原子性獲取或釋放資源(countDown -> 使state加/減1),直到getState()==0,表示沒有資料了並觸發原有執行緒繼續執行。

CycliBarriar:多個執行緒到達某一個點,然後才觸發新的程序或原有多個執行緒才繼續執行。底層使用ReentrantLock + Condition -> 使用Condition裡await來等待,然後當到達一定數量後await(——index為0)後,主執行緒執行附帶的執行緒run, 執行完後才觸發notifyAll來釋放其他執行緒去繼續執行。

Semphore:底層也是AQS, 預設非公平鎖。

鎖各種分類

悲觀鎖:使用前先申請加鎖防止其他執行緒使用,Synchronized,ReentrantLock都是

樂觀鎖:使用前不會申請鎖,使用時再判斷,Atomic系列都是。

鎖類

Synchronized: JVM內部基於進入和退出Monitor物件(monitorenter和monitorExit)來實現的。方法標記結構中使用ACC_SYNCHRONIED訪問標誌來控制。

ReentrantLock: JDK庫類,底層採用AQS實現。

ReentrantReadWriteLock: 採用ReadLock及WriteLock雙鎖實現。

鎖升級問題

無鎖,偏向鎖,輕量鎖,重量鎖

Executor 系列

ExecutorThreadPool: 將thread包裝成Worker(繼承於AQS), 使用Worker來執行thread。run()而不是start()。

ExecutorService -> ThreadPoolExecutor(min, max, keepAlive, timeunit, blocking, rejecthandler)

Executors。newSingleThreadExecutor();

Executors。newCacheThreadPool();

Executors。newFixThreadPool();

Executors。newSechduleThreadPool();

Executors。newSingalSechduleThreadPool();

ForkJoin 系列: 並行執行框架,將大任務分割成若干個小任務執行。

ForkJoinPool: 用來執行Task,或生成新的ForkJoinWorkerThread,執行 ForkJoinWorkerThread 間的 work-stealing 邏輯。ForkJoinPool 不是為了替代 ExecutorService,而是它的補充,在某些應用場景下效能比 ExecutorService 更好。

ForkJoinPool: ForkJoinWorkerThread是內部worker thread(執行), 內部有 ForkJoinPool。WorkQueue來儲存要執行的ForkJoinTask。

ForkJoinTask: 執行具體的分支邏輯,宣告以同步/非同步方式進行執行

Atomic 系列: CAS實現

其他等

雜談:

Java中的執行緒排程:

java 使用的執行緒調使用搶佔式排程, Java 中執行緒會按優先順序分配 CPU 時間片執行, 且優先順序越高越優先執行,但優先順序高並不代表能獨自佔用執行時間片,可能是優先順序高得到越多的執行時間片,反之,優先順序低的分到的執行時間少但不會分配不到執行時間。

HashMap, ConcurrentHashMap, TreeMap和ConcurrentSkipListMap的選擇

快速存取 時使用HashMap

多執行緒併發存取 時使用ConcurrentHashMap

希望按照Key排序存取時使用TreeMap。

多執行緒併發存取且希望有序,使用ConcurrentSkipListMap。