2011-07-27 27 views
6

Estoy interesado en usar ScheduledExecutorService para generar múltiples hilos para las tareas si la tarea anterior aún no ha terminado. Por ejemplo, necesito procesar un archivo cada 0.5 s. La primera tarea comienza procesando el archivo, después de 0.5 segundos si el primer subproceso no termina, el segundo subproceso se genera y comienza a procesar el segundo archivo, y así sucesivamente. Esto se puede hacer con algo como esto:ScheduledExecutorService múltiples hilos en paralelo

ScheduledExecutorService executor = Executors.newScheduledThreadPool(4) 
    while (!executor.isShutdown()) { 
     executor.execute(task); 
     try { 
      Thread.sleep(500); 
     } catch (InterruptedException e) { 
      // handle 
     } 
    } 

Ahora mi pregunta: ¿Por qué no puedo hacerlo con executor.scheduleAtFixedRate?

Lo que obtengo es que si la primera tarea lleva más tiempo, la segunda tarea se inicia tan pronto como se termine por primera vez, pero no se inicia ningún nuevo subproceso aunque el ejecutor tenga un conjunto de subprocesos. executor.scheduleWithFixedDelay es claro: ejecuta tareas con el mismo lapso de tiempo entre ellas y no importa cuánto tiempo lleve completar la tarea. Entonces probablemente entendí mal el propósito de ScheduledExecutorService.

Tal vez debería ver otro tipo de ejecutor? ¿O solo usa el código que publiqué aquí? ¿Alguna idea?

Respuesta

0

Uno de los métodos scheduleAtFixedRate es lo que estás buscando. Inicia una tarea en un hilo del grupo en el intervalo dado, incluso si las tareas anteriores no han terminado. Si se está quedando sin hilos para hacer el procesamiento, ajuste las restricciones de tamaño de la agrupación como se detalla en el ThreadPoolExecutor docs.

+1

Se vinculó al método scheduleAtFixedRate, y los estados de javadoc: "Si cualquier ejecución de esta tarea lleva más tiempo que su período, las ejecuciones posteriores pueden comenzar tarde, pero no se ejecutarán simultáneamente". Eso es exactamente lo que funciona cuando lo intenté ... scheduleWithFixedDelay tampoco encaja, ya que comienza a contar para el retraso una vez que finaliza la primera tarea. Y no importa qué tan grande sea el grupo de subprocesos. Esto es extraño para mí que ScheduledExecutorService no tiene un método para la ejecución en paralelo, o tal vez extraño o malinterpreto algo, por eso estoy preguntando :) – nesvarbu

+0

Ohh, ya veo. Me lo perdí. Supongo que la pregunta sería: "¿Son realmente la misma tarea si quieres ejecutar dos de ellos a la vez?" Si estás convencido de que lo son, entonces creo que java.util.concurrent podría no ser compatible con ese uso particular. –

5

he resuelto el problema mediante el lanzamiento de un anidado en el anonimato ejecutable en cada ejecución prevista:

final ScheduledExecutorService service = Executors.newScheduledThreadPool(POOL_SIZE); 

final Runnable command = new SlowRunnable(); 

service.scheduleAtFixedRate(
    new Runnable() { 
     @Override 
     public void run() { 
     service.execute(command); 
     } 
    }, 0, 1, TimeUnit.SECONDS); 

Con este ejemplo, habrá 1 hilo de ejecución en cada intervalo de una instrucción rápida, por lo que será sin duda ser terminado cuando el siguiente intervalo ha expirado. Los subprocesos POOL_SIZE-1 restantes ejecutarán la ejecución de SlowRunnable() en paralelo, lo que puede llevar más tiempo que la duración del intervalo único.

Tenga en cuenta que aunque me gusta esta solución ya que minimiza el código y reutiliza el mismo ScheduledExecutorService, debe tener el tamaño correcto y no se puede usar en todos los contextos: si el SlowRunnable es tan lento que se ejecutan trabajos POOL_SIZE juntos, no habrá hilos para ejecutar la tarea programada a tiempo.

Además, si configura el intervalo en 1 TimeUnit.NANOSECONDS probablemente también se vuelva demasiado lento la ejecución del principal ejecutable.

Cuestiones relacionadas