Java 從基礎到精通 — 第 8 講
安全執行線程和非同步操作
該部落格上撰寫的文章是出於教學目的而創建的。 另外,文章中的資訊可能不正確,請謹慎。
同時執行多個任務可以增加吞吐量,但也會增加共享狀態的複雜度。 在決定線程數量之前,您需要決定誰將更改狀態以及如何傳達完成和失敗。
ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(4);
try {
Future<Integer> result = executor.submit(() -> loadScore());
int score = result.get();
System.out.println(score);
} finally {
executor.shutdown();
}
當任務提交給 ExecutorService 時,執行器將管理執行緒的建立和重複使用。 Future的get使得目前執行緒等待完成,同時也會拋出任務異常。
保護共享狀態
private final Object lock = new Object();
private int gold;
public void addGold(int amount) {
synchronized (lock) {
gold += amount;
}
}
如果多個執行緒同時讀取和寫入相同的值,則操作可能會遺失或可能出現中間狀態。 Synchronized 只允許一個執行緒同時執行使用相同鎖的部分。
如果鎖定範圍太寬,等待時間就會增加,並且以不同的順序取得多個鎖可能會導致死鎖。 如果可能的話,最好減少可變共享狀態本身。
CompletableFuture
CompletableFuture<Player> playerFuture =
CompletableFuture.supplyAsync(this::loadPlayer, executor);
CompletableFuture<List<Item>> itemFuture =
CompletableFuture.supplyAsync(this::loadItems, executor);
CompletableFuture<Void> all =
CompletableFuture.allOf(playerFuture, itemFuture);
all.join();
您可以先開始獨立的任務,然後在完成任務後合併步驟。 應該清楚程式碼在哪個執行器中運行以及在哪裡處理異常。
並發不會自動使您的程式碼更快。 必須測量和管理作業大小、延遲、共享狀態和執行程序終止。