0Pricing
Java Academy · บทเรียน

การรวม Futures: allOf และ anyOf

รอ future ทั้งหมดด้วย allOf และแข่งขันกันด้วย anyOf เพื่อใช้งานตรรกะหมดเวลาและทางเลือกสำรอง

การรวม Futures: allOf และ anyOf เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงต้องรวมฟิวเจอร์

เมื่อสามารถให้งานอะซิงก์ที่เป็นอิสระต่อกันทำงานแบบขนานได้ คุณอาจต้องรอให้งานทั้งหมดหรืออย่างน้อยงานแรกเสร็จก่อนดำเนินการต่อ allOf และ anyOf รองรับทั้งสองกรณี

allOf: รอให้ฟิวเจอร์ทั้งหมดเสร็จ

CompletableFuture.allOf(futures...) ส่งคืน CompletableFuture<Void> ซึ่งจะเสร็จสมบูรณ์เมื่อฟิวเจอร์อินพุตทั้งหมดเสร็จสมบูรณ์ หากรายการใดล้มเหลว allOf ก็จะล้มเหลวด้วย

CompletableFuture<String> f1 = fetchUserAsync();
CompletableFuture<List<Order>> f2 = fetchOrdersAsync();
CompletableFuture<Double> f3 = fetchBalanceAsync();
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);
all.join(); // wait for all three
String user   = f1.join();
List<Order> orders = f2.join();
Double balance = f3.join();

การรวบรวมผลลัพธ์จาก allOf

เนื่องจาก allOf ส่งคืน Void ให้รวบรวมผลลัพธ์โดยเรียก join() บนฟิวเจอร์แต่ละรายการหลังจากเรียก allOf.join()

List<CompletableFuture<String>> futures = List.of(
    fetchAsync("url1"), fetchAsync("url2"), fetchAsync("url3"));
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
    .thenApply(v -> futures.stream()
        .map(CompletableFuture::join)
        .collect(Collectors.toList()))
    .thenAccept(results -> results.forEach(System.out::println))
    .join();

anyOf: ผลลัพธ์แรกที่เสร็จเป็นผู้ชนะ

CompletableFuture.anyOf(futures...) ส่งคืน CompletableFuture<Object> ซึ่งจะเสร็จสมบูรณ์ด้วยผลลัพธ์ของฟิวเจอร์ที่เสร็จสมบูรณ์เป็น รายการแรก โดยไม่คำนึงถึงชนิด

CompletableFuture<Object> first = CompletableFuture.anyOf(
    fetchFromCacheAsync(),
    fetchFromDbAsync(),
    fetchFromApiAsync()
);
System.out.println("Fastest result: " + first.join());

anyOf สำหรับค่าทดแทนเมื่อหมดเวลา

ให้การคำนวณจริงแข่งขันกับฟิวเจอร์ที่กำหนดเวลาหมด รายการใดเสร็จก่อนจะเป็นผู้ชนะ ซึ่งเป็นรูปแบบการจัดการเวลาหมดแบบไม่บล็อก

CompletableFuture<String> real    = fetchDataAsync();
CompletableFuture<String> timeout = CompletableFuture
    .supplyAsync(() -> {
        try { Thread.sleep(2000); } catch (InterruptedException e) {}
        return "timeout-default";
    });
String result = (String) CompletableFuture.anyOf(real, timeout).join();

orTimeout (Java 9 ขึ้นไป)

orTimeout(time, unit) จะทำให้ฟิวเจอร์เสร็จสมบูรณ์ด้วย TimeoutException หากทำงานไม่เสร็จภายในเวลาที่กำหนด สะอาดกว่ารูปแบบ anyOf ที่ใช้จัดการเวลาหมดด้วยตนเอง

CompletableFuture<String> result = fetchDataAsync()
    .orTimeout(3, TimeUnit.SECONDS)
    .exceptionally(ex -> "timeout-default");
System.out.println(result.join());

การเรียก HTTP แบบขนานด้วย allOf

กระจายการเรียกไปยังบริการหลายรายการแบบขนาน จากนั้นใช้ join เพื่อรวมผลลัพธ์ ซึ่งเร็วกว่าการเรียกตามลำดับมากเมื่อบริการต่าง ๆ เป็นอิสระต่อกัน

List<String> urls = List.of(url1, url2, url3);
List<CompletableFuture<String>> futures = urls.stream()
    .map(url -> CompletableFuture.supplyAsync(() -> httpGet(url)))
    .collect(Collectors.toList());
List<String> responses = CompletableFuture
    .allOf(futures.toArray(new CompletableFuture[0]))
    .thenApply(v -> futures.stream().map(CompletableFuture::join).collect(Collectors.toList()))
    .join();

การจัดการข้อผิดพลาดใน allOf

หากฟิวเจอร์รายการใดใน allOf ล้มเหลว ฟิวเจอร์ที่ส่งคืนจะล้มเหลวทันที ห่อฟิวเจอร์แต่ละรายการด้วย exceptionally เพื่อป้องกันไม่ให้ความล้มเหลวรายการเดียวทำให้ชุดงานทั้งหมดล้มเหลว

List<CompletableFuture<String>> safe = futures.stream()
    .map(f -> f.exceptionally(ex -> "ERROR: " + ex.getMessage()))
    .collect(Collectors.toList());
CompletableFuture.allOf(safe.toArray(new CompletableFuture[0])).join();

allOf กับชนิดที่แตกต่างกัน

allOf รับฟิวเจอร์ที่มีชนิดแตกต่างกันได้ หลังจากใช้ join ให้แปลงผลลัพธ์ของฟิวเจอร์แต่ละรายการเป็นชนิดที่คาดไว้

CompletableFuture<User> userFuture   = fetchUser(id);
CompletableFuture<Config> configFuture = fetchConfig();
CompletableFuture.allOf(userFuture, configFuture).join();
User   user   = userFuture.join();
Config config = configFuture.join();

การประกอบ allOf และ thenApply

เชื่อม thenApply ต่อกับ allOf เพื่อรวบรวมผลลัพธ์ทันทีที่ฟิวเจอร์ทั้งหมดเสร็จสมบูรณ์

CompletableFuture<String> summary =
    CompletableFuture.allOf(f1, f2, f3)
        .thenApply(v -> "User: " + f1.join() +
                       ", Orders: " + f2.join().size() +
                       ", Balance: " + f3.join());
System.out.println(summary.join());

ข้อควรพิจารณาเกี่ยวกับพูลเธรด

ฟิวเจอร์ทั้งหมดในการเรียก allOf / anyOf สามารถทำงานพร้อมกันได้ ตรวจสอบให้พูลเธรดมีเธรดเพียงพอ หรือใช้เธรดเสมือน (Java 21 ขึ้นไป) เพื่อหลีกเลี่ยงการที่เธรดไม่มีโอกาสทำงาน

// With virtual threads (Java 21+):
ExecutorService vt = Executors.newVirtualThreadPerTaskExecutor();
CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> httpGet(url), vt);

การส่งต่อการยกเลิก

allOf / anyOf จะไม่ยกเลิกฟิวเจอร์ที่เหลือโดยอัตโนมัติเมื่อรายการใดรายการหนึ่งเสร็จสมบูรณ์หรือถูกยกเลิก หากจำเป็นต้องยกเลิก ให้ยกเลิกแต่ละรายการด้วยตนเอง

CompletableFuture<Object> first = CompletableFuture.anyOf(f1, f2, f3);
first.thenRun(() -> Stream.of(f1, f2, f3).forEach(f -> f.cancel(true)));

ตรวจสอบความเข้าใจ

CompletableFuture.anyOf ส่งคืนอะไร

สรุปทบทวน

allOf รอฟิวเจอร์ทั้งหมด (รวมงานเข้าด้วยกัน) ส่วน anyOf รับผลลัพธ์แรก (แข่งขันกัน) ใช้ orTimeout สำหรับเวลาหมด และห่อฟิวเจอร์แต่ละรายการด้วย exceptionally เพื่อป้องกันไม่ให้ความล้มเหลวรายการเดียวทำให้ชุดงานทั้งหมดล้มเหลว

คำถามที่พบบ่อย

บทเรียน “การรวม Futures: allOf และ anyOf” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การรวม Futures: allOf และ anyOf” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การรวม Futures: allOf และ anyOf”

รอ future ทั้งหมดด้วย allOf และแข่งขันกันด้วย anyOf เพื่อใช้งานตรรกะหมดเวลาและทางเลือกสำรอง คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การรวม Futures: allOf และ anyOf” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การสร้างและทำ CompletableFutures ให้เสร็จสมบูรณ์
  2. การเชื่อมต่อด้วย thenApply และ thenCompose
  3. การรวม Futures: allOf และ anyOf
  4. การจัดการข้อผิดพลาดและไปป์ไลน์ HTTP แบบอะซิงโครนัส
← กลับไปที่ Java Academy