テストプログラムの2つのバリエーションを比較しています。どちらもForkJoinPool
、4コアのマシンで4スレッドで動作しています。
「モード1」では、エグゼキュータサービスのようにプールを使用します。たくさんのタスクをに投げ込みExecutorService.invokeAll
ます。通常の固定スレッドエグゼキュータサービスよりもパフォーマンスが向上します(Luceneへの呼び出しがあり、そこでI / Oが実行されます)。
ここには分割統治法はありません。文字通り、私はします
ExecutorService es = new ForkJoinPool(4);
es.invokeAll(collection_of_Callables);
「モード2」では、単一のタスクをプールに送信し、そのタスクでForkJoinTask.invokeAllを呼び出してサブタスクを送信します。したがって、から継承するオブジェクトがRecursiveAction
あり、それがプールに送信されます。そのクラスのcomputeメソッドで、も継承する別invokeAll
のクラスのオブジェクトのコレクションでを呼び出します。テストの目的で、最初のオブジェクトを一度に1つずつ送信します。スレッドの呼び出しは、ただ座ってブロックするのではなく、サブタスクの1つを自分自身で取得するため、4つのスレッドすべてがビジーであることがわかります。それがそのように機能しないかもしれないいくつかの理由を考えることができます。RecursiveAction
invokeAll
VisualVMで、モード2で監視している場合、ほとんどの場合、1つのスレッドが待機しています。私が期待しているのは、invokeAllを呼び出すスレッドが、ただじっと座っているだけでなく、呼び出されたタスクの1つですぐに機能することです。これは、通常のスレッドプールでこのスキームを試した結果として生じるデッドロックよりも確かに優れていますが、それでもどうでしょうか。他の何かが提出された場合に備えて、1つのスレッドを保留していますか?そして、もしそうなら、なぜモード1で同じ問題を起こさないのですか?
これまで、Java1.6のブートクラスパスに追加されたjsr166jarを使用してこれを実行してきました。