completefuture join vs get


95

อะไรคือความแตกต่างระหว่างCompletableFuture.get()และCompletableFuture.join()?

ด้านล่างนี้คือรหัสของฉัน:

List<String> process() {

    List<String> messages = Arrays.asList("Msg1", "Msg2", "Msg3", "Msg4", "Msg5", "Msg6", "Msg7", "Msg8", "Msg9",
            "Msg10", "Msg11", "Msg12");
    MessageService messageService = new MessageService();
    ExecutorService executor = Executors.newFixedThreadPool(4);

    List<String> mapResult = new ArrayList<>();

    CompletableFuture<?>[] fanoutRequestList = new CompletableFuture[messages.size()];
    int count = 0;
    for (String msg : messages) {
        CompletableFuture<?> future = CompletableFuture
                .supplyAsync(() -> messageService.sendNotification(msg), executor).exceptionally(ex -> "Error")
                .thenAccept(mapResult::add);

        fanoutRequestList[count++] = future;
    }

    try {
        CompletableFuture.allOf(fanoutRequestList).get();
      //CompletableFuture.allOf(fanoutRequestList).join();
    } catch (InterruptedException | ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return mapResult.stream().filter(s -> !s.equalsIgnoreCase("Error")).collect(Collectors.toList());
}

ฉันได้ลองใช้ทั้งสองวิธีแล้ว แต่ไม่เห็นผลที่แตกต่าง


11
get()ต้องการให้คุณตรวจสอบข้อยกเว้น คุณควรจะเห็นความแตกต่างเมื่อคุณเปลี่ยนจากget()การjoin()ที่คุณจะได้รับ imediately รวบรวมข้อผิดพลาดที่บอกว่าค่าInterruptedExceptionมิได้ExecutionExceptionถูกโยนลงในtryบล็อก
Holger

5
@ holi-java: join()ไม่สามารถขัดจังหวะได้
Holger

@ Holger ใช่ครับ ฉันพบว่าฉันไม่สามารถขัดจังหวะงานได้
holi-java

9
ดีgetอยู่แล้วเพราะCompletableFutureการดำเนินการFutureอินเตอร์เฟซที่เอกสารมัน join()เป็นไปได้มากว่าได้รับการแนะนำเพื่อหลีกเลี่ยงความจำเป็นในการตรวจสอบข้อยกเว้นในนิพจน์แลมด้าเมื่อรวมฟิวเจอร์ ในกรณีการใช้งานอื่น ๆ อย่าลังเลที่จะใช้สิ่งที่คุณต้องการ
Holger

1
มันสมเหตุสมผลหรือไม่ที่จะใช้ join หรือ get as ทั้งสองบล็อกบนเธรด เราไม่สามารถทำให้อะซิงโครนัสนี้แทนได้โดยใช้วิธีการจัดองค์ประกอบอื่น ๆ เพื่อสร้างห่วงโซ่ของฟังก์ชันอะซิงโครนัสหลักสูตรขึ้นอยู่กับฟังก์ชันการทำงาน แต่ในกรณีของเช่นวิธีการบริการในฤดูใบไม้ผลิที่เรียกโดยวิธีการควบคุมที่ส่งคืนอนาคตที่สมบูรณ์ได้มันสมเหตุสมผลกว่าที่จะไม่เรียกรับหรือเข้าร่วมในวิธีการบริการเลยใช่หรือไม่
Shailesh Vaishampayan

คำตอบ:


110

ข้อแตกต่างเพียงอย่างเดียวคือวิธีการที่มีข้อยกเว้น get()ถูกประกาศในFutureอินเทอร์เฟซเป็น

V get() throws InterruptedException, ExecutionException;

มีการตรวจสอบข้อยกเว้นทั้งคู่ข้อยกเว้นซึ่งหมายความว่าจำเป็นต้องจัดการในโค้ดของคุณ ดังที่คุณเห็นในโค้ดของคุณเครื่องสร้างโค้ดอัตโนมัติใน IDE ของคุณถามว่าจะสร้างบล็อกการลองจับในนามของคุณหรือไม่

try {
  CompletableFuture.allOf(fanoutRequestList).get() 
} catch (InterruptedException | ExecutionException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

join()วิธีไม่เคยโยนตรวจสอบข้อยกเว้น

public T join()

แต่จะพ่นโดยไม่เลือก CompletionException ดังนั้นคุณจึงไม่จำเป็นต้องมีบล็อกลองจับและคุณสามารถควบคุมexceptionally()วิธีการได้อย่างเต็มที่เมื่อใช้List<String> processฟังก์ชันdisscused แทน

CompletableFuture<List<String>> cf = CompletableFuture
    .supplyAsync(this::process)
    .exceptionally(this::getFallbackListOfStrings) // Here you can catch e.g. {@code join}'s CompletionException
    .thenAccept(this::processFurther);

คุณสามารถค้นหาทั้งสองอย่างget()และjoin()การนำไปใช้งานได้ที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.