在Java的Timer中,当一个TimerTask被安排时,它是否已经开始"执行"了?

11

我想澄清一下TimerTask的一些事情。 当你有以下代码:

timer.schedule(task, 60000);

如果任务安排在下一分钟内运行,那么任务对象是否已经在执行?

因为我在代码某处调用了task.cancel(),但它似乎不能阻止任务执行。我甚至记录了调用的返回值,它返回false。

当我阅读cancel方法的文档时,我产生了这个问题:

取消TimerTask并从Timer队列中删除。通常情况下,如果调用无法防止TimerTask至少运行一次,则返回false。后续调用没有任何效果。如果调用防止计划执行发生,则返回true;否则返回false。

我相信在1分钟延迟之前调用了cancel()。但是为什么cancel()返回false,任务是否已经在执行?

希望你能给我提示或解释。谢谢SO!

2个回答

20
  • 任务是否在接下来的1分钟内预定运行,那么任务对象是否已经执行

不是, 它将在60秒后准确地调用此任务的 run 方法。 如果 task.cancel() 返回 false , 那可能有三种情况:

  • 该任务被安排进行一次性执行并且已经执行 OR
  • 该任务从未被安排 OR
  • 该任务已经被取消 OR

因此,如果您确定在安排任务后的60秒内调用了 cancel, 您可能会多次调用它,并从后续的 cancel 中获得结果,或者您正在对另一个任务进行取消操作。


总的来说,我建议使用 ScheduledExecutorService 而不是 Timer

您可以使用以下代码实现所需的功能:

ScheduledExecutorService.schedule( callable, delay, timeunit )

使用 ScheduledExecutorService 的原因在此处[链接]:

  • Timer 可能会对系统时钟的更改敏感,而 ScheduledThreadPoolExecutor 则不会

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

  • 在TimerTask中抛出的运行时异常会终止该线程,从而导致定时器无法正常工作。而ScheduledThreadExecutor不仅会捕获运行时异常,还允许您自定义处理方式(通过重写ThreadPoolExecutor的afterExecute方法)。抛出异常的任务将被取消,但其他任务将继续运行。


太好了!非常精准和完整的回答。不过我仍然需要深入研究我的代码,但是感谢你提供的指导,至少我知道在哪里以及该查找什么了。 - Randy Martinez

4
我不知道为什么你的代码会返回 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

我的代码不完全像这样,但它的功能类似 ^_^ 不管怎样,谢谢你的回答! :) - Randy Martinez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接