java计时器计划任务

时间:2011-07-12 15:12:36

标签: java timer

以下情况会发生什么?

Timer t = new Timer();
t.schedule(...);
t = new Timer();

具体来说,在我将一个新的Timer实例分配给t之后,我在Timer t上安排的任务会发生什么?

5 个答案:

答案 0 :(得分:7)

他们不会消失。每个Timer对象都与后台进程相关联。即使您删除了程序中Timer的所有引用,后台进程仍将继续运行(它拥有自己对该对象的引用)。因此,该对象不会被垃圾收集。

有关详细信息,请参阅official documentation

  

对应每个Timer对象是一个后台线程,用于执行所有计时器的任务,顺序...在最后一次对Timer对象的实时引用消失并且所有未完成的任务都已完成执行后,计时器的任务执行线程正常终止(并成为垃圾收集)。但是,这可能会发生任意长的时间。

答案 1 :(得分:2)

它会毫无问题地运行。唯一的问题是,如果你无法取消第一个计时器(如果你真的想要取消它)

答案 2 :(得分:0)

API docs for Timer让我相信失去对计时器的引用根本不会影响它。看来任何计划的任务仍然会被执行。无法收集计时器实例,并且在使用该Timer计划的最后一个任务完成执行之前,应用程序无法关闭。摘自文档:

“在对Timer对象的最后一次实时引用消失并且所有未完成的任务都已完成执行之后,定时器的任务执行线程正常终止(并且变为垃圾回收)。但是,这可能会花费任意长的时间。默认情况下,任务执行线程不作为守护程序线程运行,因此它能够阻止应用程序终止。如果调用者想要快速终止计时器的任务执行线程,调用者应该调用计时器的cancel方法。“ p>

答案 3 :(得分: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);

并实现Monitor返回f.e.剩下的时间到下一个Shedule

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

答案 4 :(得分:0)

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