简体   繁体   English

java 定时器定时任务

[英]java timer scheduled tasks

What happens in the following case?在以下情况下会发生什么?

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

Specifically, what happens to the the tasks that I've scheduled on Timer t after I've assigned a new instance of Timer to t?具体来说,在我为 t 分配了一个新的 Timer 实例之后,我在 Timer t 上安排的任务会发生什么?

They doesn't go away.他们没有 go 离开。 Each Timer object is associated with a background process.每个Timer object 都与一个后台进程相关联。 Even when you remove all references to your Timer in your program, the background process will still continue to run (it holds it's own reference to the object).即使您删除了程序中对Timer的所有引用,后台进程仍将继续运行(它拥有自己对对象的引用)。 Because of this, the object will not be subject to garbage collection.因此,object 不会受到垃圾回收的影响。

See the official documentation for details.详见官方文档

Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially... After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection).对应于每个 Timer object 是一个单独的后台线程,用于按顺序执行所有 timer 的任务......在对 Timer object 的最后一次实时引用消失并且所有未完成的任务都已完成执行后,timer 的任务执行线程终止优雅地(并成为垃圾收集的对象)。 However, this can take arbitrarily long to occur.但是,这可能需要任意长的时间才能发生。

It will run without any problems.它将毫无问题地运行。 The only thing is that if you won't be able to cancel the first timer (if you actually want to cancel it)唯一的问题是,如果您无法取消第一个计时器(如果您真的想取消它)

The API docs for Timer lead me to believe that losing a reference to the timer will not affect it at all.定时器的API 文档让我相信丢失对定时器的引用根本不会影响它。 It appears that any scheduled tasks will still definitely be executed.看来,任何计划任务仍然肯定会被执行。 The timer instance cannot be garbaged collected and the app cannot shut down until the last task scheduled with that Timer has finished executing.计时器实例不能被垃圾收集,并且应用程序无法关闭,直到使用该计时器安排的最后一个任务完成执行。 Excerpt from the docs:文档摘录:

"After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection). However, this can take arbitrarily long to occur. By default, the task execution thread does not run as a daemon thread, so it is capable of keeping an application from terminating. If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the timer's cancel method." “在对定时器 object 的最后一次实时引用消失并且所有未完成的任务都已完成执行后,定时器的任务执行线程将正常终止(并成为垃圾收集的对象)。但是,这可能需要任意长时间才能发生。默认情况下,任务执行线程不作为守护线程运行,因此它能够防止应用程序终止。如果调用者想要快速终止定时器的任务执行线程,调用者应该调用定时器的取消方法。

for example例如

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

and implements Monitor that's returns fe remaining time to the next Shedule并实现将 fe 剩余时间返回到下一个 Shedule 的 Monitor

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

and Monitor和监控

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

It would depend on which Timer.schedule(..) method that you plan to utilize.这取决于您计划使用的 Timer.schedule(..) 方法。 If the timer is set to repeatedly execute then assigning a new instance of Timer to t will not cause garbage collection as the timer thread will remain active.If you set the timer for one-time execution then the object will get garbage collected..at least that's what the documentation says..如果计时器设置为重复执行,则将 Timer 的新实例分配给 t 不会导致垃圾收集,因为计时器线程将保持活动状态。如果将计时器设置为一次性执行,则 object 将被垃圾收集..at至少这就是文档所说的..

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

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