【问题标题】:When a Java TimerTask is scheduled in a Timer, is it already "executing"?当 Java TimerTask 在 Timer 中调度时,它是否已经“执行”?
【发布时间】:2011-12-25 20:33:24
【问题描述】:

我想澄清一些关于 TimerTask 的事情。当您拥有以下代码时:

timer.schedule(task, 60000);

任务计划在接下来的 1 分钟内运行的位置,任务对象是否已经在执行?

因为我在代码中的某个地方调用了 task.cancel() 但似乎调用并没有阻止

要执行的任务。我什至记录了调用的返回值,它返回 false。

我在阅读取消方法的文档时提出了我的问题:

取消 TimerTask 并将其从 Timer 的队列中删除。 通常,如果调用没有阻止 TimerTask,它会返回 false 至少运行一次。后续调用无效。如果调用阻止了计划的执行,则返回 true,否则返回 false。

我相信我在 1 分钟延迟之前调用了 cancel()。但是怎么cancel返回false,

[任务]是否已经在执行?

希望您能给我一些线索/提示,甚至对此作出解释。谢谢!

【问题讨论】:

    标签: java timer timertask


    【解决方案1】:
    • 任务计划在接下来 1 分钟内运行的位置,是否已经在执行任务对象

    不,它将在 60 秒内调用此任务的 run 方法。如果task.cancel() 返回false,这可能意味着三件事:

    • 任务被安排为一次性执行并且已经运行或
    • 从未计划过任务或
    • 任务已被取消或

    因此,如果您确定在安排任务后 60 秒之前调用 cancel,您可能会调用它多次,并从后续的 cancel 中获得结果,或者您正在调用取消不同的任务。


    一般来说,我建议反对Timer 支持ScheduledExecutorService

    您可以通过以下方式实现所需的功能:

    ScheduledExecutorService.schedule( callable, delay, timeunit )

    概述了为什么 ScheduledExecutorService 是首选方式的原因here

    • Timer 可以对系统时钟的变化敏感,ScheduledThreadPoolExecutor 不是

    • 定时器只有一个执行线程,所以长时间运行的任务会延迟其他任务。 ScheduledThreadPoolExecutor 可以配置任意数量的线程。此外,如果需要,您可以完全控制创建的线程(通过提供 ThreadFactory)

    • 在 TimerTask 中抛出的运行时异常会杀死那个线程,从而使 Timer 死掉 :-( ... 即计划任务将不再运行。ScheduledThreadExecutor 不仅捕获运行时异常,而且还允许您在需要时处理它们(通过覆盖ThreadPoolExecutor 的 afterExecute 方法)。抛出异常的任务将被取消,但其他任务将继续运行。

    【讨论】:

    • 太棒了!非常准确和完整的答案。但是,我仍然需要深入研究我的代码,但感谢您的指点,至少我知道在哪里以及要寻找什么。
    【解决方案2】:

    我不知道您的代码为什么返回false

    以下代码打印true

    import java.util.Timer;
    import java.util.TimerTask;
    
    
    public class Test {
        public static void main(String[] args) {
            Timer timer = new Timer();
            TimerTask task = new TimerTask() {
    
                @Override
                public void run() {
                    System.out.println("hi");
                }
    
            };
            timer.schedule(task, 60000);
            System.out.println(task.cancel());
        }
    }
    

    如果最后一个println 被注释,程序将打印hi

    【讨论】:

    • 我的代码不完全是这样的,但它的表现确实相似 ^_^ 但无论如何感谢您的回答! :)