Future.cancel()不会取消ScheduledExecutiorService的计划执行



我将任务安排为:

ScheduledExecutorService dataService = Executors.newScheduledThreadPool(1);
Future<?> dataTimerHandle = dataService.scheduleAtFixedRate(runnable, 100, freq, TimeUnit.MILLISECONDS);

这工作很好,没有任何缺陷。

然而,当某个标志在用户操作时变为true时,就不再需要周期性地执行该任务,只需要执行一次。然后我尝试取消任务并提交一次,如下所示:

if(!dynamicUpdate) {
    dataTimerHandle.cancel(true); 
    dataTimerHandle = dataService.submit(runnable);
}
else { //Reschedule again:
    dataTimerHandle = dataService.scheduleAtFixedRate(runnable, 100, freq, TimeUnit.MILLISECONDS);
}

但看起来runnable仍在周期性执行,cancel()没有按预期工作。有没有替代策略?

问题可能不在Future的cancel()方法中。下面是一个可以运行的小例子,它似乎正是在做你想要的事情:

import java.util.concurrent.*;
public class CancelPeriodicTask {
    public static void main(String[] args) {
        ScheduledThreadPoolExecutor scheduler = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
        scheduler.setRemoveOnCancelPolicy(true);
        try {
            new CancelPeriodicTask().test(scheduler);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            int openTasks = scheduler.shutdownNow().size();
            println("Finished, open tasks: " + openTasks);
            // openTasks will be 1 when RemoveOnCancelPolicy is false
            // and the executor is closed within the scheduled task-period.
        }
    }
    private static long sleepTime = 25L;
    public void test(ScheduledThreadPoolExecutor scheduler) throws Exception {
        // sleep 5 times at scheduled interval
        SleepTask sleepTask;
        ScheduledFuture<?> scheduledSleep = scheduler.scheduleAtFixedRate(sleepTask = new SleepTask(), 0, 2 * sleepTime, TimeUnit.MILLISECONDS);
        sleepTask.sleepTimes.await();
        println("Cancelling scheduledSleep. Done: " + scheduledSleep.isDone() + ", cancelled: " + scheduledSleep.isCancelled());
        scheduledSleep.cancel(true);
        Thread.sleep(2 * sleepTime);
        println("Running sleepTask once.");
        scheduler.submit(sleepTask);
        Thread.sleep(2 * sleepTime);
        scheduledSleep = scheduler.scheduleAtFixedRate(sleepTask, 0, 2 * sleepTime, TimeUnit.MILLISECONDS);
        println("Re-scheduled scheduledSleep. Done: " + scheduledSleep.isDone() + ", cancelled: " + scheduledSleep.isCancelled());
        Thread.sleep(5 * sleepTime);
        println("Cancelling scheduledSleep. Done: " + scheduledSleep.isDone() + ", cancelled: " + scheduledSleep.isCancelled());
        scheduledSleep.cancel(true);
    }
    class SleepTask implements Runnable {
        public final CountDownLatch sleepTimes = new CountDownLatch(5); 
        public int sleepCount;
        @Override public void run() {
            println("Sleeping " + (++sleepCount));
            try { Thread.sleep(sleepTime); } catch (Exception e) {
                e.printStackTrace();
            }
            sleepTimes.countDown();
        }
    }
    private static final long START_TIME = System.currentTimeMillis(); 
    private static void println(String msg) {
        System.out.println((System.currentTimeMillis() - START_TIME) + "t " + msg);
    }
}

这是意料之中的事,因为您将cancel命令发送到了错误的句柄。当你调用service.submit()时,它会返回一个新创建的future的句柄,并且你不能使用同一个句柄向通过其他调用创建的furt发送取消消息

显然,您可以通过sevice.shutdown()关闭executor服务,以便在某个时刻之后不启动任何可运行的提交

我认为future.cocancel方法会中断线程RUNNING线程,因此您需要在可运行类&只是回归;

相关内容

  • 没有找到相关文章

最新更新