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的選擇
快速存取
多執行緒併發存取
希望按照Key排序存取時使用TreeMap。
多執行緒併發存取