Java CompletableFuture.allOf: รอครบได้ แต่ผลลัพธ์ต้องประกอบเอง
CompletableFuture.allOf คืน future ที่เสร็จเมื่อทุกงานเสร็จ แต่ชนิดผลลัพธ์เป็น Void ถ้าต้องการค่าจริงต้องเก็บ futures ต้นทางและประกอบผลหลัง barrier ผ่านครับ
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class Main {
static <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> jobs) {
CompletableFuture<Void> done = CompletableFuture.allOf(
jobs.toArray(CompletableFuture[]::new));
return done.thenApply(ignored -> jobs.stream()
.map(CompletableFuture::join)
.toList());
}
public static void main(String[] args) {
var jobs = List.of(
CompletableFuture.completedFuture("first"),
CompletableFuture.completedFuture("second"));
var result = sequence(jobs).join();
assert result.equals(List.of("first", "second")) : result;
}
}
ผลลัพธ์ยังเรียงตาม list เดิม ไม่ใช่ลำดับที่งานเสร็จ ถ้างานใด fail barrier จะ complete exceptionally และ join() โยน CompletionException ออกมา ควรกำหนด policy ว่าจะ fail-fast เชิงธุรกิจ, เก็บ partial results หรือแปลง error เป็นค่า ก่อนประกอบ futures
allOf ไม่ได้ยกเลิกงานพี่น้องให้เองเมื่อหนึ่งงานพัง และไม่ได้จำกัด concurrency หาก input มาจากรายการใหญ่ต้องควบคุม executor หรือแบ่ง batch เพิ่ม
Recap
- เก็บ futures ต้นทางเพื่ออ่านค่าหลัง
allOf - กำหนดลำดับผลลัพธ์ให้ชัด
- ออกแบบ exception และ cancellation policy
- จำกัด concurrency แยกจาก barrier