The*_*aul 4 java clock system-clock timertask
我们希望每1000秒运行一次任务(比方说).
所以我们有
timer.scheduleAtFixedRate(task, delay, interval);
Run Code Online (Sandbox Code Playgroud)
大多数情况下,这很好.但是,这是一个嵌入式系统,用户可以更改实时时钟.如果他们在我们设置定时器之后将其设置为过去的时间,则计时器似乎直到原始实时日期/时间才执行.因此,如果他们将其设置为3天,则计时器不会执行3天:(
这是允许的行为,还是Java库中的缺陷?Oracle javadoc似乎没有提及有关依赖性的任何信息,也没有提及系统时钟的基础值.
如果允许的话,我们如何发现这个时钟变化并重新安排我们的计时器?
fge*_*fge 13
Timer查看Java 1.7 的源代码,它似乎System.currentTimeMillis()用于确定任务的下一次执行.
然而,看ScheduledThreadPoolExecutor它的来源,它使用System.nanoTime().
这意味着如果你用一个代替a,你就不会看到这种行为Timer.例如,要创建一个,请使用Executors.newScheduledThreadPool().
为什么你不会看到这种行为是因为doc System.nanoTime()所说的内容:
此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关.返回的值表示纳秒,因为一些固定但任意的原始时间 [强调我的].
至于这是否是一个bug Timer,也许......
注意,与a不同ScheduledExecutorService,a Timer支持绝对时间,也许这解释了它的使用System.currentTimeMillis(); 此外,Timer自Java 1.3以来一直存在,而System.nanoTime()只出现在1.5.
但是,使用的结果System.currentTimeMillis()是,Timer对系统的日期/时间敏感......那并不是说在Javadoc文档.
这里报道http://bugs.sun.com/view_bug.do?bug_id=4290274
类似地,当系统时钟设置为较晚的时间时,任务可能会运行多次而没有任何延迟以“赶上”错过的执行。当计算机设置为待机/休眠状态并且应用程序恢复时,就会发生这种情况(我就是这样发现的)。
这种行为也可以在 Java 调试器中通过挂起和恢复计时器线程来看到。