completefuture gabung vs get

93

Apa perbedaan antara CompletableFuture.get()dan CompletableFuture.join()?

Di bawah ini adalah kode saya:

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

Saya telah mencoba dengan kedua metode tersebut tetapi saya tidak melihat perbedaan hasilnya.

Nomeswaran
sumber
10
get()mengharuskan Anda untuk menangkap pengecualian yang dicentang. Anda harus melihat perbedaan ketika Anda mengubah dari get()ke join(), karena Anda Mulailah segera akan mendapatkan kesalahan kompilator mengatakan bahwa baik InterruptedExceptionatau ExecutionExceptiondibuang di tryblok.
Holger
5
@ holi-java: join()tidak dapat disela.
Holger
@Holger ya pak. Saya menemukan saya tidak dapat mengganggu tugas.
holi-java
9
Nah getada, karena CompletableFuturealat ini Futureantarmuka yang mengamanatkan itu. join()kemungkinan besar telah diperkenalkan, untuk menghindari keharusan untuk menangkap pengecualian yang dicentang dalam ekspresi lambda saat menggabungkan masa depan. Dalam semua kasus penggunaan lainnya, silakan gunakan apa pun yang Anda suka.
Holger
1
Apakah masuk akal untuk menggunakan join atau get sebagai blok keduanya pada utas. Tidak bisakah kita menjadikan ini sebagai asinkron dengan menggunakan metode komposisi lain untuk membuat rangkaian fungsi asinkron. Alih-alih, itu bergantung pada fungsionalitas. Tetapi dalam kasus misalnya metode layanan pada musim semi dipanggil oleh metode pengontrol yang mengembalikan masa depan yang dapat diselesaikan, lebih masuk akal untuk tidak memanggil get atau bergabung dalam metode layanan sama sekali.
Shailesh Vaishampayan

Jawaban:

106

satu-satunya perbedaan adalah bagaimana metode membuang pengecualian. get()dideklarasikan dalam Futureantarmuka sebagai

V get() throws InterruptedException, ExecutionException;

Pengecualian keduanya adalah pengecualian yang dicentang yang berarti mereka perlu ditangani dalam kode Anda. Seperti yang Anda lihat di kode Anda, generator kode otomatis di IDE Anda bertanya apakah akan membuat blok coba-tangkap atas nama Anda.

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

The join()metode tidak membuang diperiksa pengecualian.

public T join()

Sebagai gantinya, ia melempar CompletionException yang tidak dicentang . Jadi Anda tidak memerlukan blok coba-tangkap dan sebaliknya Anda dapat memanfaatkan sepenuhnya exceptionally()metode saat menggunakan List<String> processfungsi 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);

Anda dapat menemukan keduanya get()dan join()implementasinya di sini

Dawid Wróblewski
sumber