Java定时器预定任务

6
以下情况会发生什么?
Timer t = new Timer();
t.schedule(...);
t = new Timer();

具体来说,当我给定一个新的 Timer 实例给 t 后,原先在 Timer t 上已经设置好的任务会发生什么?

5个回答

9
它们不会消失。每个Timer对象都与一个后台进程相关联。即使您在程序中删除了对Timer的所有引用,后台进程仍将继续运行(它持有自己对该对象的引用)。因此,该对象将不会受到垃圾回收的影响。
有关详细信息,请参见官方文档

与每个Timer对象相对应的是一个单独的后台线程,用于顺序执行计时器的所有任务...当最后一个Timer对象的活动引用消失并且所有未完成的任务已经执行完毕时,计时器的任务执行线程会正常终止(并成为垃圾回收的对象)。但是,这可能需要任意长的时间才能发生。


后台进程的名称是什么? - Prabhakaran M

2

这将没有任何问题。唯一的问题是,如果您想要取消第一个计时器,您将无法取消它。


0

例如

private ScheduledExecutorService scheduler;
private AccurateScheduledRunnable periodic;
private ScheduledFuture<?> periodicMonitor;
private int taskPeriod = 30;
private SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
private SimpleDateFormat sdfHour = new SimpleDateFormat("HH");

. . .

  scheduler = Executors.newSingleThreadScheduledExecutor();   
            periodic = new AccurateScheduledRunnable() {

                private final int ALLOWED_TARDINESS = 200;
                private int countRun = 0;
                private int countCalled = 0;

                @Override
                public void run() {
                    countCalled++;
                    if (this.getExecutionTime() < ALLOWED_TARDINESS) {
                        countRun++;
                        dateNext = new java.util.Date();
                        dateLast = new java.util.Date();
                        long tme = dateNext.getTime();
                        tme += (taskPeriod * 60) * 1000;
                        dateNext.setTime(tme);
                        //System.out.println("");
                        //System.out.println("");
                        //System.out.println("Next Sheduled Time at : " + sdf.format(dateNext));
                        //System.out.println("Periodic Cycle In : " + (countRun) + "/" + countCalled + " at " + sdf.format(dateLast));
                        //ti.displayMessage(null, " Running Sheduled Task at " + sdf.format(new Date()), TrayIcon.MessageType.NONE);
                        distAppInfo();
                    }
                }
            };
            periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.MINUTES);
            periodic.setThreadMonitor(periodicMonitor);

并实现了监视器,返回例如到下一个计划剩余的时间

long she = periodicMonitor.getDelay(TimeUnit.SECONDS);

和监视器

abstract class AccurateScheduledRunnable implements Runnable {

    private ScheduledFuture<?> thisThreadsMonitor;

    public void setThreadMonitor(ScheduledFuture<?> monitor) {
        this.thisThreadsMonitor = monitor;
    }

    protected long getExecutionTime() {
        long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
        return delay;
    }
}

0

计时器的API文档让我相信失去对计时器的引用不会对其产生影响。似乎任何已安排的任务仍然肯定会被执行。计时器实例不能被垃圾回收,应用程序也不能关闭,直到使用该计时器安排的最后一个任务完成执行。以下是文档摘录:

“当最后一个Timer对象的活动引用消失并且所有未完成的任务都已经执行完毕时,计时器的任务执行线程将优雅地终止(并成为垃圾回收的对象)。但是,这可能需要任意长的时间才能发生。默认情况下,任务执行线程不作为守护线程运行,因此它有可能阻止应用程序终止。如果调用者想要快速终止计时器的任务执行线程,则应调用计时器的cancel方法。”


0

这取决于您计划使用哪个Timer.schedule(..)方法。如果定时器被设置为重复执行,则将新的Timer实例分配给t不会导致垃圾回收,因为定时器线程将保持活动状态。如果您将定时器设置为一次性执行,则对象将被垃圾回收..至少文档是这样说的。


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