Подтвердить что ты не робот

ScheduledExecutorService с переменной задержкой

Предположим, что у меня есть задача, которая вытягивает элементы из java.util.concurrent.BlockingQueue и обрабатывает их.

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

Как я могу запланировать/перенести задачу, если частота может быть изменена динамически?

  • Идея состоит в том, чтобы взять поток обновлений данных и распространить их в пакетном режиме на графический интерфейс
  • Пользователь должен иметь возможность изменять частоту обновлений.
4b9b3361

Ответ 1

Я не думаю, что вы можете изменить фиксированную задержку. Я думаю, вам нужно использовать schedule() для выполнения однократного выстрела и запланировать снова после завершения (с измененным временем ожидания, если требуется).

Ответ 2

Используйте schedule(Callable<V>, long, TimeUnit), а не scheduleAtFixedRate или scheduleWithFixedDelay. Затем убедитесь, что ваш Callable перенастроит себя или новый экземпляр Callable в какой-то момент в будущем. Например:

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

Этот подход позволяет избежать необходимости отключать и воссоздавать ScheduledExecutorService.

Ответ 3

Не следует ли использовать scheduleAtFixedRate, если вы пытаетесь обработать несколько задач очереди с определенным интервалом? scheduleWithFixedDelay будет ждать только указанной задержки, а затем выполнить одну задачу из очереди.

В любом случае методы schedule* в ScheduledExecutorService возвращают ссылку ScheduledFuture. Если вы хотите изменить скорость, вы можете отменить ScheduledFuture и перенести задачу с другой скоростью.

Ответ 4

scheduleWithFixedDelay (...) возвращает RunnableScheduledFuture. Чтобы перенести его, вы можете просто отменить и перенести его. Чтобы перенести его, вы можете просто обернуть RunnableScheduledFuture с помощью нового Runnable:

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