hoàn thành tham gia và nhận được


93

Sự khác biệt giữa CompletableFuture.get()và là CompletableFuture.join()gì?

Dưới đây là mã của tôi:

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

Tôi đã thử với cả hai phương pháp nhưng tôi không thấy sự khác biệt về kết quả.


10
get()yêu cầu bạn bắt các ngoại lệ đã kiểm tra. Bạn sẽ nhận thấy sự khác biệt khi bạn thay đổi từ get()sang join(), vì ngay lập tức bạn sẽ nhận được lỗi trình biên dịch nói rằng không có InterruptedExceptionhoặc không ExecutionExceptionđược ném vào trykhối.
Holger

5
@ holi-java: join()không thể bị gián đoạn.
Holger

@Holger vâng, thưa ông. Tôi thấy tôi không thể làm gián đoạn nhiệm vụ.
holi-java

9
Tồn gettại tốt , bởi vì CompletableFuturetriển khai Futuregiao diện yêu cầu nó. join()rất có thể đã được giới thiệu, để tránh cần phải bắt các ngoại lệ đã kiểm tra trong biểu thức lambda khi kết hợp tương lai. Trong tất cả các trường hợp sử dụng khác, hãy thoải mái sử dụng bất cứ điều gì bạn thích.
Holger

1
Có thực sự hợp lý khi sử dụng tham gia hoặc lấy cả hai khối trên chuỗi. Thay vào đó, chúng ta không thể làm cho điều này không đồng bộ bằng cách sử dụng các phương thức thành phần khác để tạo một chuỗi các hàm không đồng bộ. Tùy thuộc vào chức năng. Nhưng trong trường hợp ví dụ, một phương thức dịch vụ trong mùa xuân được gọi bằng phương thức bộ điều khiển trả về trong tương lai hoàn chỉnh, thì việc không gọi get hoặc join trong phương thức dịch vụ sẽ hợp lý hơn.
Shailesh Vaishampayan,

Câu trả lời:


107

sự khác biệt duy nhất là cách các phương thức ném ngoại lệ. get()được khai báo trong Futuregiao diện là

V get() throws InterruptedException, ExecutionException;

Các ngoại lệ đều là các ngoại lệ đã được kiểm tra , có nghĩa là chúng cần được xử lý trong mã của bạn. Như bạn có thể thấy trong mã của mình, một trình tạo mã tự động trong IDE của bạn đã hỏi bạn có tạo khối try-catch thay cho bạn hay không.

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

Các join()phương pháp không ném kiểm tra trường hợp ngoại lệ.

public T join()

Thay vào đó, nó ném ra CompletionException không được chọn . Vì vậy, bạn không cần khối try-catch và thay vào đó, bạn hoàn toàn có thể khai thác exceptionally()phương pháp khi sử dụng List<String> processhàm 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);

Bạn có thể tìm thấy cả hai get()join()triển khai tại đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.