Web 服務器、資料庫服務器等典型服務端應用面臨海量短小任務請求。若採用「每請求一線程」模型,頻繁創建/銷毀線程的開銷將遠超業務處理本身,且大量活躍線程會耗盡記憶體導致「切換過度」。線程池通過重用固定數量線程解決這兩大問題:
線程池結合了固定工作線程組與共享工作隊列,兼具低開銷、資源管控與調度可預測性,是高併發服務器的首選。
術語「線程池」易誤導人以為是「線程對象池」。實際高效實現是:固定線程組 + 阻塞隊列 + wait/notify 協作。調用者將 Runnable 任務入隊並 notify();工作線程從隊列 take() 任務執行,空隊列時 wait() 掛起。
public class WorkQueue {
private final int nThreads;
private final PoolWorker[] threads;
private final LinkedList<Runnable> queue = new LinkedList<>();
public WorkQueue(int nThreads) {
this.nThreads = nThreads;
threads = new PoolWorker[nThreads];
for (int i = 0; i < nThreads; i++) {
threads[i] = new PoolWorker();
threads[i].start();
}
}
public void execute(Runnable r) {
synchronized (queue) {
queue.addLast(r);
queue.notify();
}
}
private class PoolWorker extends Thread {
public void run() {
Runnable r;
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try { queue.wait(); } catch (InterruptedException ignored) {}
}
r = queue.removeFirst();
}
try { r.run(); }
catch (RuntimeException e) { /* 記錄日誌,防止線程泄漏 */ }
}
}
}
}
關鍵點:
wait() 釋放鎖讓生產者入隊;notify() 喚醒消費者。RuntimeException 防止工作線程意外終止導致線程池縮水。ExecutorService / ThreadPoolExecutor 的基礎原型。