Multi-thread mysticism (by Java) 多執行緒奧義,深入研究 Java 多執行緒相關問題的紀錄歸總。 目錄 一、關於開發多執行緒必須知道的幾件事 (基礎概念) 甚麼時候用並行 (Parallel) ? 同步 (Synchronous)、非同步 (Asynchronous) 並行 (Concurrency)、平行 (Parallelism) 阻塞 (Blocking)、非阻塞 (Non-Blocking) 死鎖 (Deadlock)、飢餓 (Starvation)、活鎖 (Livelock) mulit-thread 級別 ( 阻塞、無飢餓、無障礙、無鎖、無等待 ) Java内存模型(Java Memory Model,JMM) -> 原子性( Atomicity )、可見性( Visibility )、有序性( Ordering ) Java Thread 的 6 個生命週期狀態 (NEW、RUNNABLE、BLOCKED、WAITING、TIME_WAITING、TERMINATED) 二、Java 多執行緒基礎操作中可能被你忽略的點 多實作 Runnable 少繼承 Thread 如何合理的終止 Thread 運行(不要用 stop()方法,interrupt() 才是上上策) wait() 與 notify() 怎麼用 ? 不要用 suspend() 與 resume() join() 與 yield() volatile 可以保證可見性與有序性,但不能保證原子性 Thread Safe 與 synchronized 概念 使用 ThreadGroup 管理 Thread 們 Daemon 守護執行緒(後臺運行) Thread 的優先級,權貴與庶民 並發情況下不要用 ArrayList,改用 Vector HashMap 也不安全,改用 ConcurrentHashMap 千萬不要對 Integer 上鎖 !!! 三、Java 多執行緒高級 API synchronized() 的替代品: ReentrantLock (中斷等待、鎖申請等待時間、公平鎖) wait()、notify() 的替代品:Condition Semaphore 信號量,允許多個 Thread 同時訪問 ReadWriteLock 讀寫分離鎖 Thread 完成數量達標才放行:CountDownLatch 循環柵欄:CyclicBarrier(士兵集結完畢後再一起作戰) 取代 suspend() 與 resume() 的最佳工具:LockSupport 四、Thread Pool 系列 Executor 框架介紹 固定大小 ThreadPool 與計畫任務 探究底層:ThreadPool 的內部實作(自定義 ThreadPoolExecutor 必看) 任務太多隊列塞爆了:拒絕策略 自定義 Thread 創建:ThreadFactory 擴展 ThreadPool,繼承 ThreadPoolExecutor 合理計算並決定 ThreadPool 的 Thread 數量 在 ThreadPool 中尋找被藏起來的 Exception Fork/Join 框架(MapReduce 思想) 四、多執行緒資料結構 好用的工具:多執行緒集合類別簡介 (超難)解析高效的讀寫隊列:ConcurrentLinkedQueue 高效讀取陣列:不變模式下的 CopyOnWriteArrayList 資料共享通道:BlockingQueue 隨機資料結構:跳表(SkipList)實現部分鎖(多執行緒 Map,有序性,快速查找。) 五、開發時要注意的細節和鎖的優化 注意!減小鎖持有時間,能不上鎖就不上鎖 注意!鎖粗化(大量分散上鎖會造成浪費),能一起上鎖就一起上鎖 減小鎖粒度 鎖分離 JVM 把細節做到了極致(偏向鎖、輕量級鎖、自旋鎖、鎖消除) ThreadLocal,為每個 Thread 分配專屬於自己的資源(不用共享) 六、無鎖 不一樣的併發思維策略:比較交換(CAS) Java Pointer:Unsafe CAS 原子性操作的不足(被修改後實際值不變) 無鎖的 Thread Safe 整數:AtomicInteger 無鎖的物件引用:AtomicReference 與帶有時間戳記雙重驗證的無鎖的物件引用:AtomicStampedReference 無鎖的 Array:AtomicIntegerArray 把普通變數進化成原子化變數:AtomicFieldUpdater 實作練習:無鎖 Vector 實現挑戰