Frage

Angenommen, ich habe eine Aufgabe, die Elemente aus einem java.util.concurrent.Blockingqueue und verarbeitet.

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

Wie kann ich die Aufgabe planen / verschieben, wenn die Frequenz dynamisch geändert werden kann?

  • Die Idee besteht
  • Der Benutzer sollte in der Lage sein, die Häufigkeit von Aktualisierungen zu variieren
War es hilfreich?

Lösung

Ich glaube nicht, dass Sie eine feste Ratenverzögerung ändern können. Ich denke, Sie müssen verwenden zeitlicher Ablauf() Um einen One-Shot auszuführen und erneut zu planen, sobald dies abgeschlossen ist (mit einer geänderten Auszeit bei Bedarf).

Andere Tipps

Verwenden schedule(Callable<V>, long, TimeUnit) statt scheduleAtFixedRate oder scheduleWithFixedDelay. Stellen Sie dann sicher, dass Sie aufrufen verschieben sich selbst oder eine neue Callable -Instanz Irgendwann in der Zukunft. Zum Beispiel:

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

Dieser Ansatz vermeidet die Notwendigkeit, das zu schalten und neu zu erstellen ScheduledExecutorService.

Solltest du nicht benutzen scheduleAtFixedRate Wenn Sie versuchen, mehrere Warteschlangenaufgaben mit einem bestimmten Intervall zu bearbeiten? scheduleWithFixedDelay Warten Sie nur auf die angegebene Verzögerung und führen dann eine Aufgabe aus der Warteschlange aus.

In beiden Fällen die schedule* Methoden in a ScheduledExecutorService wird zurückkehren a ScheduledFuture Hinweis. Wenn Sie den Tarif ändern möchten, können Sie die stornieren ScheduledFuture und plante die Aufgabe mit einer anderen Rate neu.

SchedulewithFixedDelay (...) gibt eine RunnableScheduledfuture zurück. Um es neu zu planen, können Sie es einfach stornieren und neu planen. Um es neu zu planen, können Sie einfach die RunnableScheduledfuture mit einem neuen Runnable einwickeln:

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

Ich musste das kürzlich mit enderfuture tun und wollte nicht runnable oder so einwickeln. So hat ich es gemacht:

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);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top