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

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

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

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

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

person parkr    schedule 05.10.2009    source источник
comment
мне непонятно, почему вы используете блокирующую очередь. если ваша очередь пуста. Я предполагаю, что ваше запланированное задание будет заблокировано. это ваше намерение? это, вероятно, запутает время планировщика задач.   -  person Omry Yadan    schedule 05.10.2009
comment
Я выбрал реализацию ArrayBlockingQueue, так как она должна быть потокобезопасной, соблюдать порядок FIFO и быть ограниченной. Даже если задача блокируется, это не должно сбивать с толку планирование задач, не так ли?   -  person parkr    schedule 05.10.2009
comment
Вы правильно используете реализацию BlockingQueue (на самом деле ScheduledThreadPoolExecutor использует ее внутри). Однако почему вы вообще распространяете свои обновления в графическом интерфейсе с помощью таймера? Почему бы не сделать это в режиме реального времени? Не слишком ли много обновлений? Вы обеспокоены вращением потока Swing?   -  person Adamski    schedule 05.10.2009
comment
Я хочу пакетно обновлять. Таким образом, внутренние события могут поступать каждую мс, но графический интерфейс будет обновляться каждые 100 мс. Я думаю, что это будет более привлекательным визуально и будет меньше нагрузки на процессор. Я использую Eclipse RCP вместо Swing.   -  person parkr    schedule 05.10.2009
comment
Более поздний дубликат: Как изменить скорость или период повторяющейся задачи с помощью ScheduledExecutorService?   -  person Basil Bourque    schedule 15.10.2018


Ответы (5)


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

person Brian Agnew    schedule 05.10.2009
comment
Спасибо. Я сделал 'задержку' переменной экземпляра и добавил частный метод для выполнения следующих действий: } - person parkr; 06.10.2009

Используйте 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.

person Adamski    schedule 05.10.2009
comment
Вместо Callable<Void> можно (нужно?) использовать Runnable. - person Thirler; 21.11.2014
comment
Я не нахожу функцию schedule(Callable) для ScheduledExecutorService. Только те, что со всеми параметрами. Не могли бы вы указать мне, где? Или, по крайней мере, исправил пример, чтобы включить задержку 0. - person jlanza; 31.01.2017
comment

Мне пришлось сделать это недавно, используя ScheduledFuture, и я не хотел оборачивать Runnable или что-то в этом роде. Вот как я это сделал:

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);
}
person Chibueze Opata    schedule 10.10.2018

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

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

person jarnbjo    schedule 05.10.2009
comment
scheduleWithFixedDelay(...) — создает и выполняет периодическое действие, которое становится доступным сначала после заданной начальной задержки, а затем с заданной задержкой между завершением одного выполнения и началом следующего. Если какое-либо выполнение задачи сталкивается с исключением, последующие выполнения подавляются. В противном случае задача будет завершена только через отмену или прекращение исполнителя. - person parkr; 05.10.2009
comment
Можете ли вы привести пример кода отмены и переноса? Как насчет текущих обновлений? - person parkr; 05.10.2009

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

new Runnable() {
    public void run() {
        ((RunnableScheduledFuture)future).run();
    }
};
person sfussenegger    schedule 05.10.2009