Domanda

Supponiamo che io sono un compito che sta tirando gli elementi da un java.util.concurrent.BlockingQueue e il loro trattamento.

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
È stato utile?

Soluzione

Non credo che si può cambiare un ritardo tasso fisso. Penso che è necessario utilizzare schedule () per eseguire una tantum e pianificazione nuovo una volta che ha completato (con un tempo modificato se richiesto).

Altri suggerimenti

Usa schedule(Callable<V>, long, TimeUnit) piuttosto che scheduleAtFixedRate o scheduleWithFixedDelay. Quindi assicurarsi che il Callable se stesso o una nuova istanza Callable a un certo punto in futuro ripianifica. Ad 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.

Non dovresti utilizzare scheduleAtFixedRate se si sta cercando di elaborare diversi compiti di coda con un intervallo specifico? scheduleWithFixedDelay attenderà solo per il ritardo specificato e quindi eseguire un compito dalla coda.

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

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

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

Ho dovuto fare questo di recente utilizzando ScheduledFuture e non volevo avvolgere Runnable o tali. Ecco come ho fatto:

private ScheduledExecutorService scheduleExecutor;
private ScheduledFuture<?> scheduleManager;
private Runnable timeTask;

public void changeScheduleTime(int timeSeconds){
    //change to hourly update
    if (scheduleManager!= null)
    {
        scheduleManager.cancel(true);
    }
    scheduleManager = scheduleExecutor.scheduleAtFixedRate(timeTask, timeSeconds, timeSeconds, TimeUnit.SECONDS);
}

public void someInitMethod() {

    scheduleExecutor = Executors.newScheduledThreadPool(1);    
    timeTask = new Runnable() {
        public void run() {
            //task code here
            //then check if we need to update task time
            if(checkBoxHour.isChecked()){
                changeScheduleTime(3600);
            }
        }
    };

    //instantiate with default time
    scheduleManager = scheduleExecutor.scheduleAtFixedRate(timeTask, 60, 60, TimeUnit.SECONDS);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top