Pergunta

Suponha que eu tenha uma tarefa que esteja puxando elementos de um java.util.Concurrent.BlockingQueue e processando -os.

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

Como posso agendar / reagendar a tarefa se a frequência puder ser alterada dinamicamente?

  • A idéia é fazer um fluxo de atualizações de dados e propagá -las em lote para uma GUI
  • O usuário deve poder variar a frequência de atualizações
Foi útil?

Solução

Eu não acho que você possa alterar um atraso de taxa fixa. Eu acho que você precisa usar cronograma() Para executar um único tiro e agendar novamente uma vez que ele conclua (com um tempo limite modificado, se necessário).

Outras dicas

Usar schedule(Callable<V>, long, TimeUnit) ao invés de scheduleAtFixedRate ou scheduleWithFixedDelay. Em seguida, verifique se o seu chamável reagendas em si ou uma nova instância chamada em algum momento no futuro. Por exemplo:

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

Essa abordagem evita a necessidade de desligar e recriar o ScheduledExecutorService.

Você não deveria estar usando scheduleAtFixedRate Se você está tentando processar várias tarefas de fila com um intervalo específico? scheduleWithFixedDelay aguardará apenas o atraso especificado e executará uma tarefa da fila.

Em ambos os casos, o schedule* Métodos em a ScheduledExecutorService retornará um ScheduledFuture referência. Se você quiser alterar a taxa, pode cancelar o ScheduledFuture e reagendar a tarefa com uma taxa diferente.

SchedulewithFixedDelay (...) retorna um RunnablesCheduledFuture. Para reagendar, você pode apenas cancelar e reagir. Para reagendar, você pode apenas embrulhar o RunnablesCheduledFuture com um novo Runnable:

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

Eu tive que fazer isso recentemente usando o ScheduledFuture e não queria envolver o Runnable ou algo assim. Veja como eu fiz:

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);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top