Ich verwende ExecutorCompletionService, um das Ergebnis der Aufträge zu erhalten, sobald es seine Ausführung beendet. Pseudo-Code ist wie this-
Korrekte Weise, Ausgabe von ExecutorCompletionService zu erhalten
Instantiate FixedThreadPool executor, exec
Instantiate ExecutorCompletionService, completionService
for(taskList) {
completionService.submit(someTask)
}
exec.shutDown();
whie(!exec.isShutdown()) { //Line 1
Task t = completionService.take(); //Line 2
}
Wie wir wissen, shutdown()
wartet auf die Beendigung aller eingereichten Aufgaben, so lange, wie es eine Aufgabe im Gange ist, während Zustand auf Line1 gibt true zurück und Code geht in der Schleife um die abgeschlossene Aufgabe aus der Warteschlange zu übernehmen und gegebenenfalls zu warten.
Jetzt habe ich ein Problem mit dem obigen Code beobachtet, in dem Kontrolle auf Linie2 blockiert wird, selbst wenn keine weiteren Aufgaben mehr im Gange sind, alle Aufgaben abgeschlossen wurden.
Ich denke, es ist, weil ThreadPoolExecutor
den Shutdown-Prozess wieder aufnimmt, wenn die letzte Aufgabe abgeschlossen und der Abschlusswarteschlange hinzugefügt wird, da es keine ausstehenden gesendeten Aufgaben mehr gibt. Aber während es noch heruntergefahren wurde, findet die nächste Iteration statt und isShutdown()
gibt false zurück, so dass es in die Schleife geht und durch den take()
Aufruf blockiert wird, obwohl keine weiteren Aufgaben vorhanden sind. Vielleicht ist es die Zeit zwischen dem letzten Anruf und dem richtigen Pool. Denke ich in die richtige Richtung?
Also habe ich überlegt, ob dies der richtige Weg ist, um das Ergebnis vom Completion Service zu nutzen? Um dies zu beheben, kann ich die while
on line1 durch for(taskList)
ersetzen, um isShutdown
Anruf zu vermeiden. Es gibt noch eine andere Sache, ist es die beste Praxis, den Executor herunterzufahren und dann das Ergebnis vom Completion-Service zu bekommen oder zuerst das Ergebnis zu sammeln und am Ende den execturo herunterzufahren?