Java tiene un marco de trabajo paralelo similar a los bloques de construcción de subprocesos: se lo denomina estructura de unión de horquilla. Es available para usar con el actual Java SE 6 y para ser incluido en el próximo Java SE 7.
Hay recursos disponibles para comenzar con el marco, además de la documentación de la clase javadoc. Desde jsr166 page, menciona que "También hay una wiki que contiene documentación adicional, notas, consejos, ejemplos, etc. para estas clases".
fork-join examples, como la multiplicación de matrices son un buen lugar para comenzar.
Utilicé el marco fork-join para resolver algunos de Intel's 2009 threading challenges. El marco es liviano y de bajo costo: el mío fue la única entrada de Java para el problema del Kight's Tour y superó a otras entradas en la competencia. Las fuentes de Java y la documentación están disponibles en el sitio del desafío para su descarga.
EDIT:
no tengo ni idea de cómo una clase o piezas de código puede cuidar empujándolo hacia una piscina [...]
Usted puede hacer su propia tarea mediante la subclasificación de una de las subclases ForKJoinTask, como RecursiveTask. A continuación se explica cómo calcular la secuencia de fibonacci en paralelo. (Tomado de la RecursiveTask
javadocs - comentarios son mías.)
// declare a new task, that itself spawns subtasks.
// The task returns an Integer result.
class Fibonacci extends RecursiveTask<Integer> {
final int n; // the n'th number in the fibonacci sequence to compute
Fibonnaci(int n) { this.n = n; } // constructor
Integer compute() { // this method is the main work of the task
if (n <= 1) // 1 or 0, base case to end recursion
return n;
Fibonacci f1 = new Fibonacci(n - 1); // create a new task to compute n-1
f1.fork(); // schedule to run asynchronously
Fibonacci f2 = new Fibonacci(n - 2); // create a new task to compute n-2
return f2.invoke() + f1.join(); // wait for both tasks to compute.
// f2 is run as part of this task, f1 runs asynchronously.
// (you could create two separate tasks and wait for them both, but running
// f2 as part of this task is a little more efficient.
}
}
a continuación, ejecuta esta tarea y obtener el resultado
// default parallelism is number of cores
ForkJoinPool pool = new ForkJoinPool();
Fibonacci f = new Fibonacci(100);
int result = pool.invoke(f);
Este es un ejemplo trivial para mantener las cosas simples. En la práctica, el rendimiento no sería tan bueno, ya que el trabajo ejecutado por la tarea es trivial en comparación con la sobrecarga del marco de tareas. Como regla general, una tarea debe realizar algunos cálculos significativos, suficientes para que la tara general del marco sea insignificante, pero no tanto que termine con un núcleo al final del problema ejecutando una tarea grande. Dividir tareas grandes en otras más pequeñas garantiza que no se deje mucho trabajo mientras que otros núcleos están inactivos; el uso de tareas más pequeñas mantiene ocupados más núcleos, pero no tan pequeños que la tarea no funciona realmente.
[...] o cómo el código puede parecer raro cuando que necesita para hacer una copia de todo y cuánto de todo lo que se empuja en una piscina.
Solo las tareas se envían a un grupo. Lo ideal es que no desee copiar nada: para evitar interferencias y la necesidad de bloqueo, lo que ralentizaría su programa, sus tareas deberían funcionar idealmente con datos independientes. Los datos de solo lectura se pueden compartir entre todas las tareas y no es necesario copiarlos. Si los hilos necesitan cooperar para construir una gran estructura de datos, lo mejor es que construyan las piezas por separado y luego las combinen al final. La combinación se puede hacer como una tarea separada, o cada tarea puede agregar su parte del rompecabezas a la solución general. Esto a menudo requiere alguna forma de bloqueo, pero no es un problema de rendimiento considerable si el trabajo de la tarea es mucho mayor que el trabajo que actualiza la solución. La solución My Knight's Tour utiliza este enfoque para actualizar un repositorio común de recorridos en el tablero.
Trabajar con tareas y concurrencia es un cambio bastante paradigmático de la programación regular de un solo hilo. A menudo, hay varios diseños posibles para resolver un problema determinado, pero solo algunos de ellos serán adecuados para una solución con rosca. Puede tomar algunos intentos obtener la sensación de cómo volver a resolver los problemas familiares de una manera multi-hilo. La mejor forma de aprender es mirar los ejemplos y luego probarlo por ti mismo. Siempre perfil, y meausre los efectos de variar el número de hilos. Puede establecer explícitamente el número de subprocesos (núcleos) para usar en el grupo en el constructor de grupo. Cuando las tareas se dividen linealmente, puede esperar una aceleración casi lineal a medida que aumenta el número de subprocesos.