繁体   English   中英

具有可变延迟的ScheduledExecutorService

[英]ScheduledExecutorService with variable delay

假设我有一个从java.util.concurrent.BlockingQueue中提取元素并处理它们的任务。

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

如果可以动态更改频率,如何安排/重新安排任务?

  • 我们的想法是获取数据更新流并将它们批量传播到GUI
  • 用户应该能够改变更新的频率

使用schedule(Callable<V>, long, TimeUnit)而不是scheduleAtFixedRatescheduleWithFixedDelay 然后确保您的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

我认为你不能改变固定费率延迟。 我认为您需要使用schedule()执行一次性操作,并在完成后再次安排(如果需要,可以修改超时)。

如果您尝试以特定间隔处理多个队列任务,是否应该使用scheduleAtFixedRate scheduleWithFixedDelay仅等待指定的延迟,然后从队列中执行一个任务。

在任何一种情况下, ScheduledExecutorServiceschedule*方法都将返回ScheduledFuture引用。 如果要更改速率,可以取消ScheduledFuture并以不同的速率重新安排任务。

scheduleWithFixedDelay(...)返回RunnableScheduledFuture。 为了重新安排它,您可能只是取消并重新安排它。 要重新安排它,你可以用一个新的Runnable包装RunnableScheduledFuture:

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

我最近不得不使用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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM