在 Java 並發編程的世界裡,進程是執行中程序的實例,也是作業系統進行資源分配和調度的獨立單元;而線程則是進程內部的一條執行路徑,是 CPU 調度和分派的基本單元。進程擁有獨立的記憶體空間,同一進程下的多線程共享該進程的記憶體資源。Java 原生支援多線程,使得並發任務的實現變得直觀高效。
定義任務邏輯,實現 java.lang.Runnable 接口並重寫 run() 方法。此方式將任務與執行機制解耦,靈活性最高。
public class LiftOff implements Runnable {
private int countDown;
public LiftOff(int countDown) { this.countDown = countDown; }
private String status() { return countDown > 0 ? String.valueOf(countDown) : "LiftOff!"; }
@Override public void run() {
while (countDown-- > 0) { System.out.println(status()); }
}
}
java.util.concurrent.Callable<V> 的 call() 方法可返回結果或拋出異常。配合 ExecutorService.submit() 可獲取 Future<V> 物件,透過 get() 阻塞等待結果。
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) { this.id = id; }
@Override public String call() throws Exception { return "Result of TaskWithResult " + id; }
}
Thread 類構造方法接受 Runnable 任務。調用 start() 啟動新線程並執行 run()。注意:直接調用 run() 不會開啟新線程。
Runnable 或 Callable,它們僅定義任務,執行機制交由執行器(如線程池)管理,解耦更徹底。
Java 定義於 Thread.State 枚舉中:
wait()、join() 無超時)。sleep()、wait(timeout)、join(timeout))。run() 結束或異常終止。狀態轉換關係可透過 thread.getState() 監控。Java 採用搶占式調度,系統分配 CPU 時間片,避免單一線程佔用導致進程阻塞。
| 方法 | 作用 | 關鍵特性 |
|---|---|---|
sleep(ms) | 讓當前線程暫停指定毫秒 | 不釋放鎖,回到 RUNNABLE |
join() | 當前線程等待目標線程結束 | 可設超時,不釋放鎖 |
yield() | 提示調度器當前線程願意讓出 CPU | 不保證切換,不釋放鎖 |
interrupt() | 發送中斷請求,設置中斷標誌 | 僅影響阻塞操作(sleep/wait/join/NIO),I/O 與 synchronized 阻塞不可中斷 |
守護線程(Daemon)為後台服務線程(如 GC、Finalizer)。當所有非守護線程結束,JVM 退出,守護線程隨之終止。 必須在 start() 前調用 setDaemon(true)。守護線程創建的子線程默認也是守護線程。
wait():釋放鎖,進入 WAITING。notify()/notifyAll():喚醒一個/所有等待線程,重新競爭鎖。IllegalMonitorStateException。經典「打蠟/拋光」協作範例展示了雙線程交替執行的協調邏輯。
ReentrantLock 配合 Condition 提供更精細的控制:
await() 等同 wait(),signal()/signalAll() 等同 notify()/notifyAll()。try-finally 確保釋放。CountDownLatch、Semaphore、CyclicBarrier、Phaser 等。