Question

Supposons que j'ai une tâche qui tire les éléments d'un java.util.concurrent.BlockingQueue et de les traiter.

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

Comment puis-je planifier / replanifier la tâche si la fréquence peut être modifiée de manière dynamique?

  • L'idée est de prendre un flux de mises à jour de données et les propager dans le lot à une interface graphique
  • L'utilisateur doit pouvoir faire varier la fréquence des mises à jour
Était-ce utile?

La solution

Je ne pense pas que vous pouvez changer un retard à taux fixe. Je pense que vous devez utiliser schedule () pour effectuer un one-shot, et le calendrier à nouveau une fois qu'elle a terminé (avec un temps modifié si nécessaire).

Autres conseils

Utilisez schedule(Callable<V>, long, TimeUnit) plutôt que scheduleAtFixedRate ou scheduleWithFixedDelay. Assurez-vous ensuite que votre appelable elle est reprogrammée ou une nouvelle instance appelable à un moment donné à l'avenir. Par exemple:

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

Cette approche évite la nécessité d'arrêter et de recréer le ScheduledExecutorService.

Vous ne devriez pas utiliser scheduleAtFixedRate si vous essayez de traiter plusieurs tâches de file d'attente avec un intervalle spécifique? scheduleWithFixedDelay n'attendra que le délai spécifié, puis d'exécuter une tâche de la file d'attente.

Dans les deux cas, les méthodes de schedule* dans un ScheduledExecutorService renverront une référence ScheduledFuture. Si vous voulez changer le taux, vous pouvez annuler la ScheduledFuture et replanifier la tâche avec un taux différent.

scheduleWithFixedDelay (...) renvoie un RunnableScheduledFuture. Pour remettre à plus tard, vous pourriez annuler et remettre à plus tard. Pour remettre à plus tard, vous pouvez simplement envelopper l'esprit de RunnableScheduledFuture une nouvelle Runnable:

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

Je devais le faire en utilisant récemment ScheduledFuture et ne voulais pas envelopper Runnable ou tel. Voici comment je l'ai fait:

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);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top