首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 並發基礎總結:線程創建、volatile/synchronized、線程池七大參數全解析

     編輯:Java 綜合教學

Java 並發基礎總結:線程創建、volatile/synchronized、線程池七大參數全解析

並發編程是利用多核 CPU 提升吞吐量的關鍵。本文系統梳理:線程創建三種方式、volatile 可見性原理、synchronized 鎖優化演進、線程池 7 大參數與 4 種拒絕策略、任務隊列選型指南,構建並發知識骨架。

一、線程創建三種方式

方式關鍵點優缺點
繼承 Thread重寫 run()簡單,但單繼承限制,邏輯與線程控制耦合
實現 Runnable實現 run(),傳入 Thread 構造器支援多實現、邏輯解耦、可用線程池,**推薦**
實現 Callable + FutureTaskcall() 有返回值,Future.get() 阻塞獲取需獲取結果時使用,配合線程池 submit()
// Callable 範例
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<String> fut = exec.submit(() -> "hello");
System.out.println(fut.get()); // 阻塞等待結果

二、volatile:輕量級可見性保證

  • 作用:保證多線程對共享變量的可見性 (寫入立即刷主存,讀取失效本地緩存),不保證原子性
  • 底層:寫入時 lock 前綴指令 → 緩存行寫回主存 + 總線嗅探失效其他 CPU 緩存
  • 適用場景:狀態標誌位、單次初始化 (DCL 單例)、獨立觀察者模式
  • 禁用場景:複合操作 (i++、check-then-act)、需原子性時

三、synchronized:從重量級到輕量級的進化

鎖對象規則

  • 實例方法 → this
  • 靜態方法 → Class對象
  • 同步塊 → 括號內對象

JDK 1.6+ 鎖優化階梯

  1. 偏向鎖:無競爭時,CAS 標記線程 ID,後續進出無同步開銷
  2. 輕量級鎖:輕度競爭,CAS 替換 Mark Word 指向棧鎖記錄,自旋等待
  3. 膨脹鎖 (重量級):激烈競爭,OS Mutex 陷入內核,線程阻塞
  4. 鎖消除/粗化:JIT 編譯期優化,刪除無共享鎖/合併相鄰同步塊

對象頭 Mark Word 存儲鎖狀態:
無鎖(01) → 偏向鎖(01) → 輕量級鎖(00) → 重量級鎖(10) → GC標記(11)

四、線程池:ThreadPoolExecutor 七大參數

public ThreadPoolExecutor(
    int corePoolSize,      // 核心線程數 (常駐)
    int maximumPoolSize,   // 最大線程數 (峰值)
    long keepAliveTime,    // 非核心線程閒置存活時間
    TimeUnit unit,         // 時間單位
    BlockingQueue<Runnable> workQueue, // 任務隊列
    ThreadFactory threadFactory,       // 線程工廠 (命名、優先級、守護)
    RejectedExecutionHandler handler   // 拒絕策略
)

參數調優口訣

  • CPU 密集型:core = maximum = CPU 核心數 + 1,隊列用 LinkedBlockingQueue
  • IO 密集型:core = CPU 核心數 × 2,maximum 更大,隊列用 SynchronousQueue (直接提交)
  • keepAliveTime:任務耗時短且突發大 → 調大 (如 60s);長連接任務 → 調小

四大內置拒絕策略

策略行為適用場景
AbortPolicy (默認)拋 RejectedExecutionException關鍵業務,需立即感知
CallerRunsPolicy調用者線程執行任務緩衝峰值,不丟任務,不拋異常
DiscardPolicy靜默丟棄非核心日誌、監控數據
DiscardOldestPolicy丟棄隊列頭任務,重試提交優先處理新請求的場景

任務隊列選型對比

隊列特性適用池
ArrayBlockingQueue有界數組、FIFO固定大小池,需有界控制
LinkedBlockingQueue無界鏈表、FIFO、吞吐高FixedThreadPool (默認)、單一池
SynchronousQueue無容量、直接移交CachedThreadPool (默認)、高併發短任務
PriorityBlockingQueue優先級排序定時/優先任務

五、任務提交流程圖解

提交任務
    │
    ├─ 線程數 < corePoolSize → 創建核心線程執行
    │
    ├─ 線程數 ≥ corePoolSize → 入隊列
    │       ├─ 入隊成功 → 等待執行
    │       └─ 入隊失敗 (有界隊列滿)
    │             ├─ 線程數 < maximumPoolSize → 創建非核心線程執行
    │             └─ 線程數 ≥ maximumPoolSize → 執行拒絕策略
    │
    └─ 非核心線程閒置 > keepAliveTime → 回收

六、Executors 四大工廠方法對比

方法底層參數風險
newFixedThreadPoolcore=max=n, LinkedBlockingQueue隊列無界 → OOM
newCachedThreadPoolcore=0, max=Integer.MAX, SynchronousQueue線程無界 → OOM
newSingleThreadExecutorcore=max=1, LinkedBlockingQueue隊列無界 → OOM
newScheduledThreadPoolcore=n, max=Integer.MAX, DelayedWorkQueue非核心線程無界

阿里巴巴開發手冊強制:禁用 Executors 默認工廠,必須自定義 ThreadPoolExecutor 明確有界隊列與拒絕策略,防止生產 OOM。

七、最佳實踐棧單

  1. 業務線程池隔離:下單池、查詢池、異步通知池分離,避免相互影響
  2. 線程命名:new ThreadFactoryBuilder().setNameFormat("order-process-%d").build() (Guava),日誌排查秒定位
  3. 監控指標:activeCount、queueSize、taskCount、rejectCount 接入 Prometheus/Grafana
  4. 優雅關閉:shutdown() → awaitTermination() → shutdownNow(),配合 Spring @PreDestroy

核心心法:並發無銀彈,「可見性、原子性、有序性」三性權衡;線程池參數無標準答案,唯有壓測、監控、迭代。先跑通單機並發,再考慮分佈式鎖、MQ 解耦。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved