併發設計模式提供成熟的線程安全協作範式,降低同步複雜度,避免死鎖、活鎖、數據競爭。本文聚焦四大核心模式的 Java 實現要點。
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() { return INSTANCE; }
}
缺點:無法控制初始化時機,靜態字段觸發即創建。
public static synchronized Singleton getInstance() { // 每次調用加鎖
if (instance == null) instance = new Singleton();
return instance;
}
public class Singleton {
private Singleton() {}
private static class Holder {
static final Singleton INSTANCE = new Singleton(); // 類加載時初始化,JVM 保證原子性
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
原理:外部類加載不觸發內部類加載,首次調用 getInstance() 才初始化 Holder,JVM 類初始化鎖天然線程安全。
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton(); // volatile 禁止指令重排
}
}
return instance;
}
不可變對象:構造後狀態不可改變,所有字段 final、無 setter、不公開可變組件引用。
public final class ImmutablePoint {
private final int x, y;
public ImmutablePoint(int x, int y) { this.x = x; this.y = y; }
public int getX() { return x; }
public int getY() { return y; }
// 修改返回新對象
public ImmutablePoint translate(int dx, int dy) {
return new ImmutablePoint(x + dx, y + dy);
}
}
final 字段構造函數結束前可見)。String, Integer, LocalDate, Collections.unmodifiableList 等。
Future:結果佔位符,提供 get() 阻塞獲取、isDone() 輪詢、cancel() 取消。Callable:異步任務,有返回值、可拋異常。ExecutorService:任務提交與執行分離。ExecutorService executor = Executors.newFixedThreadPool(4);
Future future = executor.submit(() -> {
Thread.sleep(2000); // 模擬耗時計算
return "Result-" + System.currentTimeMillis();
});
// 主線程可做其他事
doOtherWork();
try {
String result = future.get(3, TimeUnit.SECONDS); // 限時阻塞獲取
System.out.println("Got: " + result);
} catch (TimeoutException e) {
future.cancel(true); // 中斷執行中的任務
}
CompletableFuture.supplyAsync(() -> fetchUser(id), executor)
.thenApply(user -> user.getName())
.thenApply(name -> name.toUpperCase())
.thenAccept(System.out::println)
.exceptionally(ex -> { log.error("Failed", ex); return "DEFAULT"; });
BlockingQueue queue = new LinkedBlockingQueue<>(100); // 有界隊列提供背壓
// 生產者
new Thread(() -> {
while (running) {
Task task = produce();
queue.put(task); // 隊列滿時阻塞
}
}).start();
// 消費者
new Thread(() -> {
while (running) {
Task task = queue.take(); // 隊列空時阻塞
consume(task);
}
}).start();
poison pill 特殊任務或 ExecutorService.shutdown() + 隊列 drainTo()。PriorityBlockingQueue 支援任務優先級。適用極高吞吐(千萬級 ops/s),預分配數組、CAS 序列號、緩存行填充避免偽共享,適合日誌、事件溝通、金融撮合引擎。
// 1. 生產者提交任務到有界隊列
BlockingQueue requestQueue = new LinkedBlockingQueue<>(1000);
// 2. 工作線程池消費,返回 CompletableFuture
ExecutorService workers = new ThreadPoolExecutor(8, 16, 60, TimeUnit.SECONDS, requestQueue);
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
Request req = requestQueue.take();
return process(req);
}, workers);
// 3. 回調鏈處理結果
future.thenAcceptAsync(response -> sendResponse(response), ioExecutor);
| 模式 | 核心解決問題 | Java 關鍵技術 |
|---|---|---|
| 單例 | 全局唯一實例、延遲初始化 | 靜態內部類 / volatile DCL |
| 不可變 | 共享數據線程安全 | final 字段、無 setter、防禦性拷貝 |
| Future | 異步計算與主流程解耦 | ExecutorService、CompletableFuture 鏈式編程 |
| 生產者消費者 | 異步解耦、背壓控制 | BlockingQueue、Disruptor、ThreadPoolExecutor |
實際架構中常組合使用:單例管理線程池/隊列 → 生產者提交任務 → Future/CompletableFuture 承接結果 → 不可變對象傳遞數據,構建高內聚、低耦合、線程安全的併發系統。