首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 高併發設計模式精講:單例、不可變、Future、生產者消費者

     編輯:Java 相關知識

設計模式在併發中的價值

併發設計模式提供成熟的線程安全協作範式,降低同步複雜度,避免死鎖、活鎖、數據競爭。本文聚焦四大核心模式的 Java 實現要點。

1. 單例模式:線程安全的延遲初始化

❌ 餓漢式(類加載即創建)

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 類初始化鎖天然線程安全。

⚠️ 雙重檢查鎖(DCL,需 volatile)

private static volatile Singleton instance;
public static Singleton getInstance() {
    if (instance == null) {
        synchronized (Singleton.class) {
            if (instance == null)
                instance = new Singleton(); // volatile 禁止指令重排
        }
    }
    return instance;
}

2. 不可變模式:天然線程安全

不可變對象:構造後狀態不可改變,所有字段 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 字段構造函數結束前可見)。
  • 自由共享,作為 Map 鍵、集合元素無副作用。
  • 簡化併發推理,消除死鎖風險。

JDK 不可變類

String, Integer, LocalDate, Collections.unmodifiableList 等。

3. Future 模式:異步計算與結果佔位符

核心角色

  • Future:結果佔位符,提供 get() 阻塞獲取、isDone() 輪詢、cancel() 取消。
  • Callable:異步任務,有返回值、可拋異常。
  • ExecutorService:任務提交與執行分離。

JDK 內置實現

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:鏈式組合(JDK 8+ 推薦)

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"; });

4. 生產者-消費者模式:解耦與背壓

阻塞隊列實現(標準庫)

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();

關鍵設計點

  • 有界隊列:防止生產過快導致 OOM,自然實現背壓。
  • 優雅關閉:poison pill 特殊任務或 ExecutorService.shutdown() + 隊列 drainTo()。
  • 多消費者負載均衡:單隊列多消費者自動競爭取任務。
  • 優先級隊列:PriorityBlockingQueue 支援任務優先級。

Disruptor:高性能無鎖環形隊列

適用極高吞吐(千萬級 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 承接結果 → 不可變對象傳遞數據,構建高內聚、低耦合、線程安全的併發系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved