繁体   English   中英

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

[英]Future.cancel() is not cancelling the scheduled execution of ScheduledExecutorService

我将任务安排为:

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);
    }

}

这是预期的,因为您将取消命令发送到错误的句柄。 当您调用service.submit()它将返回新创建的future的句柄,并且您不能使用完全相同的句柄将取消消息发送到通过其他调用创建的future的消息。

显然,您可以通过sevice.shutdown()关闭执行程序服务,以在一段时间后不启动任何可运行的提交

我认为,future.cancel方法会中断RUNNING线程的线程,因此您需要在runnable类中捕获InterruptedException并仅返回即可。

暂无
暂无

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

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