2009-10-05 20 views
12

Supponiamo di avere un task che sta richiamando elementi da un java.util.concurrent.BlockingQueue ed elaborandoli.ScheduledExecutorService con ritardo variabile

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

Come posso programmare/riprogrammare l'attività se la frequenza può essere modificata in modo dinamico?

  • L'idea è quella di prendere un flusso di aggiornamenti dei dati e li propagano in batch per una GUI
  • L'utente deve essere in grado di variare la frequenza degli aggiornamenti
+0

Non mi è chiaro il motivo per cui si sta utilizzando una coda di blocco. se la tua coda è vuota. Presumo che l'attività pianificata verrà bloccata. è questa la tua intenzione? questo probabilmente confonderà i tempi del programmatore dell'attività. –

+0

Ho scelto l'implementazione ArrayBlockingQueue in quanto deve essere protetta da thread, rispettare l'ordinamento FIFO ed essere limitata. Anche se blocchi l'attività, non dovrebbe confondere la pianificazione delle attività dovrebbe? – parkr

+0

Si sta utilizzando correttamente un'implementazione BlockingQueue (infatti ScheduledThreadPoolExecutor ne utilizza uno internamente). Tuttavia, perché stai propagando gli aggiornamenti alla GUI usando un timer? Perché non farlo in tempo reale? Ci sono troppi aggiornamenti? Sei preoccupato per la rotazione del filo di Swing? – Adamski

risposta

6

Non penso che sia possibile modificare un ritardo di frequenza fissa. Penso che sia necessario utilizzare schedule() per eseguire uno scatto singolo e riprogrammare una volta completato (con un timeout modificato, se necessario).

+1

Grazie - ho reso "ritardato" una variabile di istanza e aggiunto un metodo privato per eseguire le seguenti operazioni: while (! ExecutorService.isShutdown) {executorService.schedule (nuova attività (coda), ritardo, TimeUnit.MILLISECONDS); } – parkr

1

Non dovresti utilizzare scheduleAtFixedRate se si sta tentando di elaborare diverse attività di coda con un intervallo specifico? scheduleWithFixedDelay attenderà solo il ritardo specificato e quindi eseguirà un'attività dalla coda.

In entrambi i casi, i metodi schedule* in un ScheduledExecutorService restituiscono un riferimento ScheduledFuture. Se si desidera modificare la tariffa, è possibile annullare ScheduledFuture e riprogrammare l'attività con una frequenza diversa.

+0

scheduleWithFixedDelay (...) - Crea ed esegue un'azione periodica che viene abilitata per la prima volta dopo il dato ritardo iniziale e successivamente con il ritardo specificato tra la fine di una esecuzione e l'inizio della successiva. Se qualsiasi esecuzione dell'attività riscontra un'eccezione, le esecuzioni successive vengono soppresse. In caso contrario, l'attività terminerà solo tramite annullamento o cessazione dell'esecutore. – parkr

+0

Puoi dare un esempio di codice di cancellazione e riprogrammazione? Che dire di eventuali aggiornamenti in corso? – parkr

0

scheduleWithFixedDelay (...) restituisce un RunnableScheduledFuture. Per riprogrammarlo, potresti semplicemente annullare e riprogrammare. Per ripianificare esso, si può solo avvolgere il RunnableScheduledFuture uno spirito nuovo Runnable:

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

Usa schedule(Callable<V>, long, TimeUnit) piuttosto che scheduleAtFixedRate o scheduleWithFixedDelay. Quindi assicurati che il tuo Callable si aggiorni da solo o una nuova istanza di Callable in futuro. Per esempio:

// 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); 

Questo approccio evita la necessità di spegnere e ricreare il ScheduledExecutorService.

+0

Invece di 'Callable ' puoi (dovresti?) Usare 'Runnable'. – Thirler

+0

@Thirler: Sì, questo è un punto giusto. – Adamski

+0

Non trovo la funzione 'schedule (Callable)' per un ScheduledExecutorService. Solo quelli con tutti i parametri. Potresti per favore indicarmi dove? O almeno fissato l'esempio per includere un ritardo di 0. – jlanza

Problemi correlati