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

Java 多執行緒實戰避坑指南:已淘汰方法、死鎖/活鎖/資源耗盡與除錯技巧

     編輯:Java 相關知識

多執行緒實戰四大經典問題

1. 已淘汰方法:stop/suspend/resume

  • stop():強制終止執行緒,釋放所有鎖 → 破壞資料一致性,留下受損物件。
  • suspend():暫停執行緒但持有鎖 → 極易造成死鎖。
  • resume():配合 suspend 使用,同樣風險。

替代方案:使用 interrupt() + 旗標檢查 + Thread.interrupted() 協作式停止。

2. 死鎖

定義

執行緒 A 持有鎖 1 等待鎖 2,執行緒 B 持有鎖 2 等待鎖 1,雙方永久阻塞。

預防:固定鎖獲取順序

// 錯誤:順序不一致
// Thread A: lock(A) → lock(B)
// Thread B: lock(B) → lock(A)

// 正確:全域固定順序
private static final Object LOCK1 = new Object();
private static final Object LOCK2 = new Object();

void methodA() {
    synchronized (LOCK1) {
        synchronized (LOCK2) { /* ... */ }
    }
}

void methodB() {
    synchronized (LOCK1) { // 相同順序
        synchronized (LOCK2) { /* ... */ }
    }
}

其他策略

  • tryLock(timeout):超時放棄,避免永久等待。
  • 鎖層級化:細粒度鎖替代單一大鎖。
  • 避免在同步區塊呼叫外部/未知代碼。

3. 活鎖

執行緒持續嘗試操作但永遠失敗(如兩人走廊相讓),CPU 100% 但無進展。

緩解

  • 隨機退避:Thread.sleep(random.nextInt(100))。
  • 指數退避重試。
  • 公平鎖/佇列機制。

4. 記憶體損壞與資源耗盡

  • 記憶體損壞:非同步存取共享資料 → 用 synchronized、volatile、Atomic* 修正。
  • 資源耗盡:執行緒過多耗盡檔案描述符、資料庫連線、記憶體。
    • 解決:資源池(連線池、執行緒池、物件池)。
    • ExecutorService 限制並發數。
    • Semaphore 控制許可數。

5. 大量執行緒除錯技巧

自訂探測執行緒

public class ThreadProbe extends Thread {
    @Override
    public void run() {
        while (true) {
            Thread[] threads = new Thread[1000];
            int count = Thread.enumerate(threads);
            for (int i = 0; i < count; i++) {
                Thread t = threads[i];
                System.out.printf("%s\t%d\t%b\t%b%n",
                    t.getName(), t.getPriority(), t.isAlive(), t.isDaemon());
            }
            try { Thread.sleep(5000); } catch (InterruptedException ignored) {}
        }
    }
}

標準工具

  • jstack :列印所有執行緒堆疊(含鎖資訊,死鎖偵測)。
  • jconsole/VisualVM:圖形化監控執行緒狀態、記憶體、CPU。
  • ThreadMXBean:程式化取得執行緒資訊、偵測死鎖。

6. 除錯最佳實務清單

  1. 命名有意義的執行緒名稱:thread.setName("OrderProcessor-1")。
  2. 使用 ThreadLocal 隔離執行緒專屬資料。
  3. 記錄關鍵同步點進入/離開日誌。
  4. 單元測試覆蓋並發場景(ConcurrencyTestRunner、jcstress)。
  5. 生產環境啟用 -XX:+PrintConcurrentLocks 協助 jstack 分析。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved