ForkJoinPool bleibt während invokeAll / join stehen

Ich versuche einForkJoinPool meine CPU-intensiven Berechnungen zu parallelisieren. Mein Verständnis für einen ForkJoinPool ist, dass er so lange funktioniert, wie eine Aufgabe ausgeführt werden kann. Leider habe ich häufig Worker-Threads im Leerlauf / Warten beobachtet, sodass nicht alle CPUs ausgelastet sind. Manchmal habe ich sogar zusätzliche Worker-Threads beobachtet.

Ich habe das nicht erwartet, da ich streng versucht habe es zu benutzennicht blockierend Aufgaben. Meine Beobachtung ist denen von sehr ähnlichForkJoinPool scheint einen Thread zu verschwenden. Nachdem ich viel in ForkJoinPool debuggt habe, habe ich eine Vermutung:

Ich habe invokeAll () verwendet, um die Arbeit auf eine Liste von Unteraufgaben zu verteilen. Nachdem invokeAll () die erste Aufgabe selbst ausgeführt hat, wird die Verbindung zu den anderen Aufgaben hergestellt. Dies funktioniert einwandfrei, bis die nächste Aufgabe, der Sie beitreten möchten, ganz oben in der Ausführungswarteschlange steht. Leider habe ich zusätzliche Aufgaben asynchron übermittelt, ohne sie zu verknüpfen. Ich habe erwartet, dass das ForkJoin-Framework diese Aufgabe zuerst weiter ausführt und dann zu den verbleibenden Aufgaben zurückkehrt.

Aber es scheint nicht so zu funktionieren. Stattdessen wird der Worker-Thread beim Aufruf von wait () angehalten, bis der wartende Task fertig ist (vermutlich von einem anderen Worker-Thread ausgeführt). Ich habe dies nicht überprüft, aber es scheint ein allgemeiner Fehler beim Aufrufen von join () zu sein.

ForkJoinPool bietet eineasyncModeDies ist jedoch ein globaler Parameter und kann nicht für einzelne Übermittlungen verwendet werden. Ich möchte jedoch, dass meine asynchron gegabelten Aufgaben bald ausgeführt werden.

Warum führt ForkJoinTask.doJoin () eine verfügbare Aufgabe nicht einfach über der Warteschlange aus, bis sie fertig ist (entweder von sich selbst ausgeführt oder von anderen gestohlen)?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage