在探討多線程之前,必須先釐清「進程」與「線程」的關係。進程是程式執行時的一個實例,擁有獨立的記憶體空間;而線程則是進程內部的執行單元,可被視為獨自佔有 CPU 時間執行程式碼的實體。早期的單線程系統(如 DOS)中,進程與線程是一體的。現代作業系統支援多線程,讓多個線程看似並行執行,實則透過分時調度共享 CPU 資源。在多核心處理器上,線程更能真正並行運作,大幅提升程式效能。
關鍵差異在於:線程共享進程的位址空間,多線程可同時讀寫相同記憶體區域以交換資料,但這也帶來同步與死鎖的風險。
多線程的核心價值在於提升執行效率。以五個獨立線程為例,其 CPU 耗時分別為 4、5、1、2、7 單位。若循序執行共需 19 單位;採用多線程並行,總耗時將顯著低於 19 單位(具體取決於可並行的線程組合)。大規模系統中,線程間交互更能展現效能優勢。
Java 將線程機制內建於語言核心,提供豐富的 API 支援。建立線程主要有兩種方式:
Thread 類別並覆寫 run() 方法Runnable 介面,將實例傳給 Thread 建構子呼叫 start() 啟動線程,執行緒將持續運作直到 run() 返回為止。Java 線程特性包括:主線程從 main 開始;各線程獨立循序執行;線程間獨立但需協作機制;共享記憶體空間但需妥善同步控制;區域變數線程私有,實例變數可共享但需存取權限控制。
Java 中所有物件皆內建鎖,透過 synchronized 關鍵字獲取。同一時刻,某類別實例的同步方法或區塊僅允許單一線程執行,確保共享資源存取的原子性。
控制有限資源存取的經典機制。定義可用連接數;線程佔用時減一、釋放時加一。以下為簡易實作:
class Semaphore {
private int count;
public Semaphore(int count) { this.count = count; }
public synchronized void acquire() {
while (count == 0) {
try { wait(); } catch (InterruptedException e) { /* 重試 */ }
}
count--;
}
public synchronized void release() {
count++;
notify(); // 喚醒等待線程
}
}
| 分類 | 成員 | 說明 |
|---|---|---|
| 常數 | MAX_PRIORITY | 最高優先級 (10) |
| MIN_PRIORITY | 最低優先級 (1) | |
| NORM_PRIORITY | 標準優先級 (5) | |
| 方法 | Thread() | 建立線程 |
| run() | 線程執行本體 (實作 Runnable 時) | |
| setPriority(int) | 設定優先級 | |
| start() | 啟動線程 | |
| sleep(long millis) | 線程休眠指定毫秒 | |
| yield() | 暫讓 CPU 給其他線程 |
情境:夫妻同帳戶同時提款,若無同步機制,deduct() 方法可能被兩線程同時通過檢查,導致超額提款。解決方案:在 deduct() 加上 synchronized,確保檢查與扣款的原子性。
public class Account {
private float total;
public synchronized boolean deduct(float t) {
if (t <= total) {
total -= t;
return true;
}
return false;
}
}
經典多線程協作模型。Producer 隨機生成產品放入 Warehouse,Consumer 隨機取出。倉庫類別需實作同步的 put() 與 take() 方法,利用 wait()/notify() 協調雙方節奏,避免缓衝區溢位或空取。
此模式廣泛應用於任務佇列、訊息傳遞等系統,展現線程間透過共享物件協作的核心範式。