2017-10-30 3 views
3

Meine Intuition ist, dass der folgende Code falsch ist. Ich glaube, da join() verwendet wird, werden alle Ausnahmen, die während der Fertigstellung der Futures geworfen werden, deaktiviert. Wenn dann get() aufgerufen wird, gibt es keine geprüften Ausnahmen, keine Protokollierung von Fehlern und Schwierigkeiten beim Diagnostizieren von Fehlern während eines Fehlers.CompleteFuture Ausnahmeverhalten mit Join() dann get()

List<CompletableFuture> list = ImmutableList.of(future1, future2); 
    CompletableFuture.allOf(list.toArray(new CompletableFuture[list.size()])).join(); 

    try { 
     result1 = future1.get(); 
     result2 = future2.get(); 

    } catch (InterruptedException | ExecutionException e) { 
     // will this ever run if join() is already called? 
    } 

Ich habe die Dokumentation für CompletableFuture durchgesehen, aber habe nicht die genaue Antwort auf meine Frage gefunden. Ich frage hier und werde dann den Quellcode durchlesen. Der einzige Grund, warum ich sehen kann, dass der catch-Block-Code ausgeführt wird, ist, wenn irgendwie überprüfte Ausnahmen in einem Ausführungskontext gespeichert und nicht in join() geworfen (oder durch eine ungeprüfte Ausnahme umbrochen) geworfen werden und dann erneut geworfen werden in irgendeiner Form nach get(). Das erscheint mir unwahrscheinlich.

Also meine ultimative Frage ist, wird der Catch-Block-Code jemals ausgeführt werden?

+1

warum nicht einfach direkt verwenden: 'CompletableFuture.allOf (neue CompletableFuture [] {future1, future2}). Join();' – Lino

+0

@Lino Klar, das klingt viel einfacher. Arbeiten an einer gemeinsamen Codebasis und das ist nicht mein Code. – user3527174

+1

herausgefunden, dass es noch einfacher sein kann: verwenden Sie einfach 'CompletableFuture.allOf (future1, future2) .join();' – Lino

Antwort

3

Sowohl die join und die get Verfahren blockieren Methode, die nach Abschluss Signale setzt und gibt das Ergebnis T:

Die einfachere Art und Weise, dies zu tun wie diese ohnehin wäre. Die Verarbeitung des Stück Code wie in Frage: -

Auf der einen Seite InterruptedException geworfen werden könnte, während der Faden in den Prozess des Wartens unterbrochen wird, da wir eine get tun, wird das Warten hier bereits durch die join Verfahren abgeschlossen.

Auch, wie in der Dokumentation join Methode angegeben

/** 
* ... if a 
* computation involved in the completion of this 
* CompletableFuture threw an exception, this method throws an 
* (unchecked) {@link CompletionException} with the underlying 
* exception as its cause. 
*/ 

Also, auf der anderen Seite, die ExecutionException für futureN.get() in Ihrem Fall könnte nur geworfen werden, ob und wann die Zukunft außerordentlich abgeschlossen. Da die Zukunft, wenn sie ausnahmsweise ausgeführt wird, am Ende einen CompletionException für den join-Aufruf werfen würde, würde sie den Catch-Block niemals erreichen oder dafür try blockieren.

0

Ja, der Code würde nie erreicht werden, aber das macht den "Code falsch".

Zuerst machen wir es einfach ausprobieren ...

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> { 
     throw new IllegalArgumentException(); 
    }); 
    try 
    { 
     CompletableFuture.allOf(future1).join(); 
    } 
    catch (Exception e1) 
    { 
     System.out.println("I'd exit here."); // *1 
    } 

    try 
    { 
     future1.get(); 
    } 
    catch (InterruptedException | ExecutionException e) 
    { 
     System.out.println("Entered!"); 
    } 

Da Sie nicht die try/catch „* 1“ tat, würde die Ausnahme des Verfahrens führen zu beenden und die get() würde nie erreicht werden; also würde die zweite catch-Klausel niemals ausgeführt werden.

Die catch ist jedoch immer noch notwendig, weil es für den Compiler ist, der die vorherige Aufrufsequenz nicht kennen kann.

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> { 
     throw new IllegalArgumentException(); 
    }); 
    try 
    { 
     CompletableFuture.allOf(future1).join(); 
     future1.get(); 
    } 
    catch (CompletionException e1) // this is unchecked, of course 
    { 
     System.out.println("Exception when joining"); 
    } 
    catch (InterruptedException | ExecutionException e) 
    { 
     System.out.println("Exception when getting"); 
    } 
Verwandte Themen