2010-11-25 9 views
5

que hava un programa Java, una sección de la misma es cálculo intensivo, como este¿Cómo multiprocesar un segmento de código de cálculo intensivo en Java?

for i = 1 :512 
    COMPUTE INTENSIVE SECTION 
end 

quiero dividirlo en múltiples hilos, hacen que sea más rápido cuando se ejecuta.

COMPUTE INTENSIVE SECTION no es secuencial. Significa ejecutar i = 1 primero o i = 5 puños son lo mismo ...

¿Alguien puede darme una gran guía sobre esto. ¿Cómo hacerlo? ¡Gracias de verdad! ¡Feliz día de gracias!

+1

El "gran guía" a esto es el excelente libro [Java concurrencia en la práctica] (http://www.javaconcurrencyinpractice.com/), por Brian Goetz et al. –

+1

http://download.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html The Fork/Join Framework está construido para ese caso (y otros, también :-). Advertencia: solo JDK7. – helpermethod

+0

BTW ¿Alguien sabe por qué Oracle pone enlaces JDK7 en el tutorial mucho antes de que esté disponible una versión de lanzamiento de JDK7? –

Respuesta

3

suena como un grupo de subprocesos sería bueno. Básicamente, usted prepara una colección de N hilos diferentes, y luego los solicita en un bucle. La solicitud bloquea hasta que un hilo esté disponible.

ThreadPool pool = Executors.newFixedThreadPool(10); // 10 threads in the pool 
ArrayList<Callable> collectionOfCallables = new ArrayList<Callable>(); 
for (...) { 
    Callable callable = new Callable<Foo>() { public Foo call() { COMPUTE INTENSIVE SECTION } } 
    collectionOfCallables.add(callable); 
} 

ArrayList<Future<Foo>> results = pool.invokeAll(collectionOfCallables); 

pool.awaitTermination(5, TimeUnit.MINUTES); // blocks till everything is done or 5 minutes have passed. 

Con el futuro no es necesario esperar la finalización. get() el resultado de un futuro se bloqueará hasta que se complete (o se cancele) el hilo correspondiente.

+0

Puede encontrar Runtime.availableProcessors() es un buen tamaño para su grupo de subprocesos. Se puede usar para cambiar dinámicamente el tamaño del grupo dependiendo del tamaño de su máquina. –

+0

Dependiendo de lo que esté sucediendo, 1 hilo por procesador puede no ser el mejor camino a seguir ... especialmente cuando se toman en cuenta trucos de procesador como "hyper threading". Sin embargo, el conteo del procesador será un factor ... buen punto. –

3

vistazo a cualquiera de Java multi-threading tutorial, ya sea la oficial:

o algunos de los otros, por ejemplo:

5

Debe leer la Concurrency Trail del Java Tutorial. Especialmente Executors y Thread Pools deberían ser relevantes para usted.

Básicamente, se crea un grupo de subprocesos (que es un Executor) a través de uno de los métodos de fábrica en the Executors class y se somete a ella Runnable casos:

for(int i = 0; i < 512; i++){ 
    executor.execute(new Runnable(){public void run(){ 
     // your heavy code goes here 
    }}); 
} 
+1

Si se trata de una tarea de cálculo intensivo, usar 'Executors.newFixedThreadPool (Runtime.getRuntime(). GetAvailableProcessors())' como ejecutor es una buena apuesta para el número de subprocesos en el grupo de subprocesos. –

0

Similar a la respuesta de Sean Patrick Floyd, pero un poco menos detallado con una expresión lambda:

ExecutorService es = Executors.newCachedThreadPool(); 
for(int i = 0; i < 512; i++){ 
    es.execute(() -> { 
     // code goes here 
    }); 
} 
+0

Entonces, esto es posible desde Java 8 en adelante. –

0

Si usted puede dividir su acción intensiva a recursivas sub tareas más pequeñas, ForkJoinPool es ideal para usted.

Si el servidor se está ejecutando con 8 core CPU, se puede ajustar el tamaño de la piscina como 8

ForkJoinPool forkJoinPool = new ForkJoinPool(8); 

O

puede utilizar Executor ServiceFixedThreadPool moviendo tarea intensiva de cómputo a Callable como a continuación

ExecutorService executorService = Executors.newFixedThreadPool(8); 

Future future = executorService.submit(new Runnable() { 
public void run() { 
    System.out.println("Your compute intensive task"); 
} 
}); 

future.get(); //returns null if the task has finished correctly. 

Hay una ventaja con ForkJoinPool. Los subprocesos inactivos robarán trabajos de subprocesos activos de blokcingQueue donde se hayan enviado las tareas Runnable/Callable.

Java 8 añade una más nueva API en Executors: newWorkStealingPool

Si es necesario esperar a la finalización de todas las tareas, el uso puede utilizar invokeAll() en ExecutorService.

Tener un vistazo a este article por Benjamin concurrentes para las API avanzadas utilizando Java 8

Cuestiones relacionadas