[FIXED] Warten auf eine Liste der Zukunft

Ausgabe

Ich habe eine Methode, die a Listvon Futures zurückgibt

List<Future<O>> futures = getFutures();

Jetzt möchte ich warten, bis entweder alle Futures erfolgreich verarbeitet wurden oder eine der Aufgaben, deren Ausgabe von einem Future zurückgegeben wird, eine Ausnahme auslöst. Selbst wenn eine Aufgabe eine Ausnahme auslöst, macht es keinen Sinn, auf die anderen Futures zu warten.

Einfacher Ansatz wäre zu

wait() {

   For(Future f : futures) {
     try {
       f.get();
     } catch(Exception e) {
       //TODO catch specific exception
       // this future threw exception , means somone could not do its task
       return;
     }
   }
}

Aber das Problem hier ist, wenn zum Beispiel der 4. Future eine Ausnahme auslöst, dann werde ich unnötig warten, bis die ersten 3 Futures verfügbar sind.

Wie löst man das? Wird der Countdown-Latch in irgendeiner Weise helfen? Ich kann Future nicht verwenden, isDoneweil das Java-Dokument sagt

boolean isDone()
Returns true if this task completed. Completion may be due to normal termination, an exception, or cancellation -- in all of these cases, this method will return true.

Lösung

Sie können einen CompletionService verwenden , um die Futures zu erhalten, sobald sie bereit sind, und wenn einer von ihnen eine Ausnahme auslöst, die Verarbeitung abzubrechen. Etwas wie das:

Executor executor = Executors.newFixedThreadPool(4);
CompletionService<SomeResult> completionService = 
       new ExecutorCompletionService<SomeResult>(executor);

//4 tasks
for(int i = 0; i < 4; i++) {
   completionService.submit(new Callable<SomeResult>() {
       public SomeResult call() {
           ...
           return result;
       }
   });
}

int received = 0;
boolean errors = false;

while(received < 4 && !errors) {
      Future<SomeResult> resultFuture = completionService.take(); //blocks if none available
      try {
         SomeResult result = resultFuture.get();
         received ++;
         ... // do something with the result
      }
      catch(Exception e) {
             //log
         errors = true;
      }
}

Ich denke, Sie können weiter verbessern, um alle noch ausgeführten Aufgaben abzubrechen, wenn einer von ihnen einen Fehler auslöst.


Beantwortet von –
dcernahoschi


Antwort geprüft von –
Katrina (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like