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

Java 多線程核心知識體系:從基礎 API 到並發控制完整總結

     編輯:Java 相關知識

線程啟動:start() vs run()

// ❌ 錯誤:直接調用 run(),單線程順序執行
thread.run(); 

// ✅ 正確:start() 創建新線程,異步執行 run()
thread.start();

start() 請求 JVM 創建新線程,進入就緒狀態;run() 只是普通方法調用,不具備多線程特性。

ThreadLocal:線程隔離變量

public class ThreadLocalDemo {
    // 靜態 ThreadLocal,每線程獨立副本
    private static final ThreadLocal threadCounter = 
        ThreadLocal.withInitial(() -> 0);
    
    public static void increment() {
        threadCounter.set(threadCounter.get() + 1);
    }
    
    public static int get() {
        return threadCounter.get();
    }
    
    public static void remove() {
        threadCounter.remove(); // 防內存洩漏,線程池必須調用
    }
}
  • 空間換時間:每線程獨存副本,無鎖競爭
  • 適用場景:數據庫連接、Session 管理、事務上下文、請求鏈路追蹤 ID
  • 內存洩漏風險:線程池場景必須 remove(),否則 Key 弱引用失效,Value 強引用無法 GC

wait/notify/snotifyAll 與 IllegalMonitorStateException

// ❌ 拋出 IllegalMonitorStateException:無同步鎖
public void badWait() {
    this.wait(); // 必須在 synchronized(this) 或 synchronized 方法中
}

// ✅ 正確:持有對象鎖
public synchronized void goodWait() throws InterruptedException {
    this.wait(1000); // 釋放鎖,進入等待集
}

public synchronized void notifyOthers() {
    this.notifyAll(); // 喚醒等待集線程,進入鎖池競爭
}

核心規則:調用 wait/notify 必須持有該對象的監視器鎖,否則拋出 IllegalMonitorStateException(RuntimeException,無需捕獲)。

sleep vs wait vs yield vs suspend 對比

方法所屬類釋放鎖用途備註
sleep(ms)Thread❌ 保持鎖定時暫停靜態方法,作用於當前線程
wait()Object✅ 釋放鎖線程通信需在同步塊中,進入等待集
yield()Thread❌ 保持鎖禮讓 CPU就緒狀態,不保證調度
suspend()Thread❌ 保持鎖掛起線程已棄用,極易死鎖

靜態同步 vs 實例同步

public class SyncDemo {
    // 類鎖:Class 對象,鎖住整個類
    public synchronized static void staticMethod() { }
    
    // 對象鎖:this,僅鎖住當前實例
    public synchronized void instanceMethod() { }
}
  • 靜態同步方法鎖:SyncDemo.class,全類範圍互斥
  • 實例同步方法鎖:this,實例範圍互斥
  • 兩者互不干擾:靜態鎖不阻塞實例鎖,反之亦然

同步實例方法互斥驗證

public class SyncTest {
    public synchronized void method1() { sleep(1000); }
    public synchronized void method2() { sleep(1000); }
    
    public static void main(String[] args) {
        SyncTest obj = new SyncTest();
        new Thread(() -> obj.method1()).start(); // Thread-1
        new Thread(() -> obj.method2()).start(); // Thread-2
        // 輸出順序:method1 完成後 method2 才開始(串行)
    }
}

同一對象的多個同步實例方法互斥,因共享 this 鎖。不同對象則不互斥。

最佳實踐清單

  1. 優先使用 java.util.concurrent 高級組件(ReentrantLock、CountDownLatch、Semaphore、ConcurrentHashMap)
  2. 同步塊最小化:縮小鎖範圍,避免在同步中調用耗時操作/IO
  3. 避免嵌套鎖:嚴格按順序獲取多把鎖,防死鎖
  4. 不可變對象:無狀態天然線程安全
  5. 線程池管理:Executors 或自定義 ThreadPoolExecutor,拒絕策略、監控指標
  6. 異步編程:CompletableFuture、虛擬線程 (JDK 21+)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved