代码之家  ›  专栏  ›  技术社区  ›  parkr

具有可变延迟的ScheduledExecutorService

  •  17
  • parkr  · 技术社区  · 15 年前

    假设我有一个任务,从java.util.concurrent.blockingqueue中提取元素并对其进行处理。

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

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

    • 其思想是获取数据更新流并将其批量传播到GUI
    • 用户应该能够改变更新的频率
    5 回复  |  直到 6 年前
        1
  •  7
  •   ThomasH    10 年前

    我认为你不能改变固定费率的延迟。我想你需要用 schedule() 执行一次放炮,并在完成后再次计划(如果需要,可修改超时)。

        2
  •  26
  •   Steve McLeod    11 年前

    使用 schedule(Callable<V>, long, TimeUnit) 而不是 scheduleAtFixedRate scheduleWithFixedDelay . 然后确保你的呼叫 重新计划自身或新的可调用实例 在未来的某个时候。例如:

    // 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
  •  2
  •   jarnbjo    15 年前

    你不应该用 scheduleAtFixedRate 如果您试图以特定的时间间隔处理多个队列任务? scheduleWithFixedDelay 将只等待指定的延迟,然后从队列执行一个任务。

    在这两种情况下, schedule* A方法 ScheduledExecutorService 将返回 ScheduledFuture 参考文献。如果要更改费率,可以取消 计划未来 以不同的速度重新安排任务。

        4
  •  0
  •   sfussenegger    15 年前

    scheduleWithFixedDelay(…)返回runnablescheduledFuture。为了重新安排,您可以取消并重新安排。要重新安排时间,您只需将RunnableScheduledFuture包装为新的Runnable:

    new Runnable() {
        public void run() {
            ((RunnableScheduledFuture)future).run();
        }
    };
    
        5
  •  0
  •   Chibueze Opata    6 年前

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