單線程程序:任務串行執行。例如 DVD 播放器——讀取磁盤 → 解碼處理 → 顯示輸出。磁盤 I/O 期間,CPU 空閒等待,性能極差。
多線程程序:將任務分解為「讀取線程」「解碼線程」「渲染線程」並行運行。I/O 與計算重疊,CPU 利用率最大化,整體吞吐率顯著提升。JVM 內部大量使用多線程(GC、JIT 編譯、類加載等)正是基於此原理。
public class SimpleThread extends Thread {
public SimpleThread(String str) { super(str); }
@Override public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try { sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
}
// 啟動
new SimpleThread("Do it!").start();
new SimpleThread("Definitely not!").start();
輸出交織無序,體現線程調度的非確定性:隨機 sleep + 搶佔式調度導致每次運行結果不同。
new Thread(new MyRunnable()).start()主線程需等待工作線程完成:thread.join() 或 join(timeout)。超時機制防止無限等待。
航空訂座系統:兩用戶搶同一座位。
解決:synchronized 關鍵字鎖定關鍵區域,保證「檢查-設置」原子性:
protected synchronized int reserveSeat(Seat seat) {
if (!seat.isReserved()) { seat.setReserved(); return 0; }
return -1;
}
JDK 5+ 提供 java.util.concurrent.locks 更靈活的鎖機制(ReentrantLock, ReadWriteLock 等)。
線程 A 持鎖 1 等鎖 2,線程 B 持鎖 2 等鎖 1 → 永久阻塞。
預防:固定全局獲鎖順序、避免嵌套鎖、使用 tryLock(timeout)、引入死鎖檢測工具。
線程創建/銷毀消耗系統資源。最佳實踐:啟動時預創建固定數量線程池,任務提交到隊列,線程循環取任務執行。
JDK 5 引入 java.util.concurrent.ExecutorService 框架(ThreadPoolExecutor, Executors 工廠),極大簡化使用。
硬件演進對線程數的影響:
| 處理器類型 | 核心數 | 超線程 | 邏輯執行管道數 | 建議線程數 |
|---|---|---|---|---|
| 雙核 Pentium 4 (HT) | 2 | 是 | 4 | 4 |
| 雙顆 Xeon (HT, 無多核) | 2 | 是 | 4 | 4 |
| 現代多核 (如 8 核 HT) | 8 | 是 | 16 | 16~32 (視 I/O 比例) |
Intel 持續增加核心數而非單核頻率,利用多核紅利的唯一途徑就是多線程並行。
多核/超線程時代,多線程是榨乾硬件性能的鑰匙。Java 提供了從基礎 Thread、synchronized 到高級 java.util.concurrent 完整工具箱。掌握線程池配置、鎖優化、死鎖預防、硬件感知調優,是構建高性能 Java 系統的核心能力。