Ответ 1
Я не думаю, что вы можете изменить фиксированную задержку. Я думаю, вам нужно использовать schedule() для выполнения однократного выстрела и запланировать снова после завершения (с измененным временем ожидания, если требуется).
Предположим, что у меня есть задача, которая вытягивает элементы из java.util.concurrent.BlockingQueue и обрабатывает их.
public void scheduleTask(int delay, TimeUnit timeUnit)
{
scheduledExecutorService.scheduleWithFixedDelay(new Task(queue), 0, delay, timeUnit);
}
Как я могу запланировать/перенести задачу, если частота может быть изменена динамически?
Я не думаю, что вы можете изменить фиксированную задержку. Я думаю, вам нужно использовать schedule() для выполнения однократного выстрела и запланировать снова после завершения (с измененным временем ожидания, если требуется).
Используйте 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
.
Не следует ли использовать scheduleAtFixedRate
, если вы пытаетесь обработать несколько задач очереди с определенным интервалом? scheduleWithFixedDelay
будет ждать только указанной задержки, а затем выполнить одну задачу из очереди.
В любом случае методы schedule*
в ScheduledExecutorService
возвращают ссылку ScheduledFuture
. Если вы хотите изменить скорость, вы можете отменить ScheduledFuture
и перенести задачу с другой скоростью.
scheduleWithFixedDelay (...) возвращает RunnableScheduledFuture. Чтобы перенести его, вы можете просто отменить и перенести его. Чтобы перенести его, вы можете просто обернуть RunnableScheduledFuture с помощью нового Runnable:
new Runnable() {
public void run() {
((RunnableScheduledFuture)future).run();
}
};