2015-05-01 10 views
5

las ich einen großen Artikel über die fork-join framework in Java 7, und die Idee ist, dass mit ForkJoinPool und ForkJoinTask können die Fäden im Pool die Unteraufgaben von anderen Aufgaben zu bekommen, so dass es weniger Threads zu verwenden ist in der Lage mehr Aufgaben zu bewältigen.Unterschied zwischen ForkJoinPool und normalem ExecutionService?

Dann habe ich versucht, eine normale ExecutorService zu verwenden, um die gleiche Arbeit zu tun, und ich kann den Unterschied nicht feststellen, da, wenn ich eine neue Aufgabe an den Pool übergeben, wird die Aufgabe auf einem anderen verfügbaren Thread ausgeführt werden.

Der einzige Unterschied, den ich feststellen kann, ist, wenn ich ForkJoinPool benutze, muss ich den Pool nicht an die Aufgaben übergeben, weil ich task.fork() aufrufen kann, um es in einem anderen Thread ausgeführt wird. Aber mit normalen ExecutorService, muss ich den Pool an die Aufgabe übergeben, oder machen Sie es eine statische, so dass innerhalb der Aufgabe, kann ich anrufen pool.submit(newTask)

Vermisse ich etwas?

(Sie können den Wohn Code aus https://github.com/freewind/fork-join-test/tree/master/src sehen)

+2

Es gibt ein paar Artikel, die erklären, welcher von diesen beiden bei verschiedenen Arten von Aufgaben besser ist. Soweit ich mich erinnere, Fork-Join-Pool ist besser (und sicher) für rekursive Art der Aufgabenplanung. In einem Szenario, in dem eine Task neue Tasks für denselben ExecutorService erzeugt (an dem sie ausgeführt wird), besteht eine hohe Wahrscheinlichkeit eines Deadlocks, wenn die Größe des Pools des ExecutorService nicht groß genug ist. Dies ist jedoch kein Fall bei Fork-Join-Pools. –

Antwort

5

Obwohl ForkJoinPool implementiert ExecutorService, es Konzeptionell unterscheidet sich von 'normalen' Vollstrecker ist.

Sie können den Unterschied leicht erkennen, wenn Ihre Aufgaben mehr Aufgaben hervorbringen und warten, bis sie abgeschlossen sind, z. durch Aufrufen

In einem normalen Executor-Dienst blockiert das Warten auf andere Aufgaben den aktuellen Thread. Es gibt zwei mögliche Ergebnisse: Wenn Ihr Executor-Dienst eine feste Anzahl von Threads hat, kann es Deadlocks, wenn der letzte laufende Thread darauf wartet, dass eine andere Aufgabe abgeschlossen wird. Wenn Ihr Executor bei Bedarf dynamisch neue Threads erstellt, kann die Anzahl der Threads explodieren und Sie haben Tausende von Threads, die zu einem Verhungern führen können.

Im Gegenteil, die Gabel/Rahmen kommt wieder verwendet den Faden in der Zwischenzeit andere Aufgaben auszuführen, so wird es nicht Deadlock, obwohl die Anzahl der Threads festgelegt ist:

new MyForkJoinTask().invoke(); 

Also, wenn Sie ein Problem haben dass Sie rekursiv lösen können, denken Sie an die Verwendung einer ForkJoinPool, da Sie einfach eine Ebene der Rekursion als ForkJoinTask implementieren können.

Überprüfen Sie einfach die Anzahl der laufenden Threads in Ihren Beispielen.