ForkJoinPool parece desperdiciar un hilo

Estoy comparando dos variaciones en un programa de prueba. Ambos funcionan con un @ de 4 hilForkJoinPool en una máquina con cuatro núcleos.

En el 'modo 1', uso el grupo como un servicio de ejecutor. Lanzo un montón de tareas enExecutorService.invokeAll. Obtengo un mejor rendimiento que el de un servicio ordinario de ejecutor de subprocesos fijos (a pesar de que hay llamadas a Lucene, que hacen algunas E / S, allí).

Aquí no hay divide y vencerás. Literalmente, hago

ExecutorService es = new ForkJoinPool(4);
es.invokeAll(collection_of_Callables);

En 'modo 2', envío una única tarea al grupo y, en esa tarea, llamo a ForkJoinTask.invokeAll para enviar las subtareas. Entonces, tengo un objeto que hereda deRecursiveAction, y se envía al grupo. En el método de cálculo de esa clase, llamo a lainvokeAll en una colección de objetos de unadiferent clase que también hereda deRecursiveAction. Para fines de prueba, envío solo uno por vez de los primeros objetos. Lo que esperaba ingenuamente era ver qué ocupaban los cuatro hilos, como el hilo que llamabainvokeAll tomaría una de las subtareas para sí mismo en lugar de simplemente sentarse y bloquear. Puedo pensar en algunas razones por las que podría no funcionar de esa manera.

Mirando en VisualVM, en el modo 2, un hilo casi siempre está esperando. Lo que espero ver es el hilo que llama a invokeAll inmediatamente va a funcionar en una de las tareas invocadas en lugar de quedarse quieto. Esto es ciertamente mejor que los puntos muertos que resultarían de probar este esquema con un grupo de subprocesos ordinario, pero aún así, ¿qué pasa? ¿Está reteniendo un hilo en caso de que se envíe algo más? Y, si es así, ¿por qué no el mismo problema en el modo 1?

Hasta ahora he estado ejecutando esto usando el jsr166 jar agregado a la ruta de clase de arranque de java 1.6.

Respuestas a la pregunta(4)

Su respuesta a la pregunta