2009-10-05 17 views
12

Supongamos que tengo una tarea que está extrayendo elementos de un java.util.concurrent.BlockingQueue y procesándolos.ScheduledExecutorService with variable delay

public void scheduleTask(int delay, TimeUnit timeUnit) 
{ 
    scheduledExecutorService.scheduleWithFixedDelay(new Task(queue), 0, delay, timeUnit); 
} 

¿Cómo puedo programar/reprogramar la tarea si la frecuencia puede cambiarse dinámicamente?

  • La idea es tener un flujo de actualizaciones de datos y propagarlas en el lote a una interfaz gráfica de usuario
  • El usuario debe ser capaz de variar la frecuencia de las actualizaciones
+0

No tengo claro por qué está utilizando una cola de bloqueo. si la cola está vacía. Supongo que su tarea programada será bloqueada. es esa tu intención? esto probablemente confundirá el tiempo del programador de tareas. –

+0

Elegí la implementación de ArrayBlockingQueue, ya que tiene que ser segura para los hilos, respetar el orden FIFO y estar limitada. Incluso si la tarea bloquea, no debería confundir la programación de la tarea si es así? – parkr

+0

Tiene razón al usar una implementación BlockingQueue (de hecho, ScheduledThreadPoolExecutor usa una internamente). Sin embargo, ¿por qué estás propagando tus actualizaciones a la GUI usando un temporizador? ¿Por qué no hacerlo en tiempo real? ¿Hay demasiadas actualizaciones? ¿Te preocupa que el hilo Swing gire? – Adamski

Respuesta

6

No creo que pueda cambiar un retraso de velocidad fija. Creo que debe usar schedule() para realizar una única toma, y ​​programar de nuevo una vez que se haya completado (con un tiempo de espera modificado si es necesario).

+1

Gracias - Hice 'demorar' una variable de instancia y agregué un método privado para hacer lo siguiente: while (! ExecutorService.isShutdown) {executorService.schedule (new Task (queue), delay, TimeUnit.MILLISECONDS); } – parkr

1

No deberías estar usando scheduleAtFixedRate si está intentando procesar varias tareas de cola con un intervalo específico? scheduleWithFixedDelay solo esperará el retraso especificado y luego ejecutará una tarea desde la cola.

En cualquier caso, los métodos schedule* en un ScheduledExecutorService devolverán una referencia ScheduledFuture. Si desea cambiar la tasa, puede cancelar el ScheduledFuture y reprogramar la tarea con una tarifa diferente.

+0

scheduleWithFixedDelay (...): crea y ejecuta una acción periódica que se habilita primero después de la demora inicial dada, y posteriormente con el retraso entre la finalización de una ejecución y el comienzo de la siguiente. Si cualquier ejecución de la tarea encuentra una excepción, las ejecuciones posteriores se suprimen. De lo contrario, la tarea solo terminará a través de la cancelación o la terminación del ejecutor. – parkr

+0

¿Puedes dar un ejemplo de código de cancelación y reprogramación? ¿Qué hay de las actualizaciones en progreso? – parkr

0

scheduleWithFixedDelay (...) devuelve RunnableScheduledFuture. Para reprogramarlo, puede cancelarlo y reprogramarlo. Para volver a programarlo, es posible que sólo envolver el ingenio RunnableScheduledFuture un nuevo Ejecutable:

new Runnable() { 
    public void run() { 
     ((RunnableScheduledFuture)future).run(); 
    } 
}; 
22

Uso schedule(Callable<V>, long, TimeUnit) en lugar de scheduleAtFixedRate o scheduleWithFixedDelay. Luego, asegúrese de que su Callable se reprograme a sí mismo o una nueva instancia de Callable en algún momento en el futuro. Por ejemplo:

// Create Callable instance to schedule. 
Callable<Void> c = new Callable<Void>() { 
    public Void call() { 
    try { 
    // Do work. 
    } finally { 
    // Reschedule in new Callable, typically with a delay based on the result 
    // of this Callable. In this example the Callable is stateless so we 
    // simply reschedule passing a reference to this. 
    service.schedule(this, 5000L, TimeUnit.MILLISECONDS); 
    } 
    return null; 
    } 
} 

service.schedule(c); 

Este enfoque evita la necesidad de apagar y volver a crear la ScheduledExecutorService.

+0

En lugar de 'Callable ' puede (¿debería?) Usar 'Runnable'. – Thirler

+0

@Thirler: Sí, ese es un punto justo. – Adamski

+0

No encuentro la función 'schedule (Callable)' para un ScheduledExecutorService. Solo los que tienen todos los parámetros. ¿Podría indicarme dónde? O al menos solucionó el ejemplo para incluir un retraso de 0. – jlanza