2010-01-07 11 views
9

Estoy escribiendo un algoritmo de optimización que crea aproximadamente 100 hilos. Actualmente, los inicio todos al mismo tiempo (for-loop) y luego le digo a cada hilo que debe unirse().Java aproximadamente 100 hilos paralelos, gestión de memoria

Mi problema ahora es que cada subproceso utiliza mucha memoria, por lo que la excepción de espacio dinámico no tardará mucho. Quiero algún tipo de programación, pero no sé cómo implementarlo.

Tengo algo como esto en mente: comience 10 hilos y cada vez que uno de estos acabados comience uno nuevo. De modo que siempre hay 10 hilos a la vez hasta que no quede ningún hilo.

¿Alguien tiene una idea o sabe cómo realizar algo como esto?

Muchas gracias y saludos de Colonia

Marco

+3

Si está interesado en Java y concurrencia, recomiendo encarecidamente este libro: http://www.javaconcurrencyinpractice.com/ –

Respuesta

1

Tenga en cuenta la cantidad de núcleos en la máquina que va a utilizar. El rendimiento será mejor si la cantidad de hilos que ejecuta normalmente es igual a la cantidad de núcleos. Como dice KLE, usa un grupo de subprocesos.

+0

Actualmente corro 2 veces porque es un Core2Duo de Intel. El rendimiento se ve bien ... – Marco

+4

esto podría ser cierto si está totalmente vinculado a la CPU, pero si hay operaciones de bloqueo (por ejemplo, IO, suspensión, ciertos tipos de bloqueo), entonces generalmente desea más hilos que núcleos para mantener el núcleos utilizados por completo. – mikera

2

En lugar de comenzar un nuevo hilo para hacer una nueva tarea, que es mucho mejor que:

  • tienen una cola de tareas a ejecutar (en lugar de hilos de ejecución)
  • utilizar una menor grupo de hilos (según lo mencionado por Michael) para procesar estas tareas.

La diferencia de velocidad y memoria es enorme, ya que no es necesario iniciar y detener un hilo para cada tarea.

El paquete java.util.concurrent explica todo sobre esto. Un libro sería más fácil de leer, aunque :-(

4

He aquí un ejemplo para empezar En primer lugar, lo que necesita para importar:.

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

Y entonces lo que hay que poner dentro de su método:

ExecutorService pool = Executors.newFixedThreadPool(10); 
    for(final Task task: tasks) { 
     pool.execute(new Runnable() { 
      @Override 
      public void run() { 
       task.execute(); 
      } 
     }); 
    } 
    pool.shutdown(); 
    while(!pool.awaitTermination(1, TimeUnit.SECONDS)) { 
     System.out.println("Waiting for tasks to shutdown"); 
    } 

Algunas notas sobre lo anterior:

  • tendrá que implementar su propio clase de tareas que realmente implementa su algoritmo
  • La clase de trabajo no tiene que simplemente tener un método de ejecución (de hecho, si que tiene esa firma, que acaba de podría obtener su tarea de implementar Ejecutable y evitar la clase interna anónima)
  • Tendrá que asegurarse de que todo lo que usa esté correctamente sincronizado . Las clases en java.util.concurrent.atomic son bastante buenas si ha compartido el estado que necesita actualizar (por ejemplo, si desea para tener un contador para cuántas tareas ha procesado).
  • Normalmente solo desea que se ejecuten tantos hilos como núcleos /cpus en su máquina. A menudo, el rendimiento de aumenta cuando el número de hilos disminuye. Normalmente solo usa más hilos si sus tareas pasan mucho tiempo bloqueadas.