並發程式設計挑戰
- 死結、活結、飢餓
- 手工管理執行緒池複雜易錯
- 缺乏非阻塞演算法支援
- 等待/通知機制易誤用
JSR-166 核心組件 (java.util.concurrent)
Executor 架構
// 執行緒池
ExecutorService pool = Executors.newFixedThreadPool(10);
// 提交任務
pool.submit(() -> doWork());
// 關閉
pool.shutdown();
ThreadPoolExecutor 自訂
public class CustomPool extends ThreadPoolExecutor {
public CustomPool(int core, int max, long keepAlive) {
super(core, max, keepAlive, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
}
@Override protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
log("執行前: " + r);
}
@Override protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t != null) log("異常: " + t);
log("執行後: " + r);
}
@Override protected void terminated() {
super.terminated();
log("執行緒池已終止");
}
}
非阻塞佇列與生產者/消費者
// 無界非阻塞佇列
BlockingQueue queue = new LinkedBlockingQueue<>();
// 生產者
pool.submit(() -> {
while (running) {
Order order = receiveOrder();
queue.put(order); // 滿時阻塞
}
});
// 消費者 (可實作 Callable 回傳結果)
class OrderProcessor implements Callable {
public Integer call() {
int count = 0;
while (running) {
Order order = queue.take(); // 空時阻塞
process(order);
count++;
}
return count;
}
}
執行緒協調工具
CountDownLatch:等待多項任務完成
CyclicBarrier:多執行緒同步屏障
Semaphore:許可證控制並發度
Exchanger:雙執行緒資料交換
Phaser:階段式同步 (Java 7+)
原子變數與 CAS
AtomicInteger counter = new AtomicInteger(0);
// 原子遞增
int old = counter.getAndIncrement();
// CAS 更新
counter.compareAndSet(expected, newValue);
最佳實務
- 優先使用高層 API (Executor、CompletableFuture)
- 避免手工 synchronized,改用 Lock、Atomic、Concurrent 集合
- 正確處理中斷:檢查
Thread.interrupted()
- 使用
ThreadLocal 隔離執行緒狀態
- 鎖排序避免死結,設定逾時