Java定时器是如何在胁迫下工作的



我有一个简单的计时器,它每分钟调用一个方法进行后台处理。它被称为:

EmailSender singletonSender = new EmailSender(cog);
timer.scheduleAtFixedRate(singletonSender, 60000, 60000);

每一分钟它都会收到一个事件,检查是否有任何理由发送电子邮件,发送电子邮件,然后就完成了。

这一切都假设系统已经启动并运行,并且有可用的CPU周期。如果电脑坐在那里无所事事,而且处理起来很快,这一切都很容易理解。但我找不到关于当电脑太忙或进入睡眠/休眠模式时这种行为的文档。

如果电脑处于睡眠状态,会发生什么情况

在检查了许多令人困惑的日志之后,我终于进行了测试。让它打印出日志声明和当前时间。我在7:30(大约)把电脑放进睡眠状态,10分钟后(大约)叫醒了它。这是日志跟踪:

BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:24:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:25:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:26:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:27:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:28:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:29:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:30:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:31:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:41:28
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:42:28

它似乎发送了一堆"追赶"事件。换句话说,就好像它们在电脑睡觉时堆积在电脑里,一旦机器重新激活,它们就会大量涌现。就好像所有的事件都是生成的,但由于无法传递而受阻,最后,当计算机启动时,所有的事件如洪水般涌了出来。

这是否被记录为旨在以这种方式工作?很明显,这会对系统的设计产生影响。合乎逻辑的是,如果你预计每天有1440个活动,那么你最终会得到1440个事件。然而,如果你只是在做后台处理,并且每个调用都完成了所有等待的后台工作,那么这些额外的调用就没有意义了。您将希望设计方法来非常快速地处理这些额外的大量调用。

如果接听电话需要一分钟以上,该怎么办

根据以上证据,如果计算机非常繁忙,则可能是您的事件发送延迟,但您仍然可以获得所有事件。因此,如果一个事件的处理需要一分钟以上的时间,问题是:你能确信该事件不会到达另一个线程吗?换言之:你确信在最后一次调用完成之前,你的处理程序永远不会被调用吗。Timer机制试图隐藏被调用线程的详细信息,假设所有调用都是在一个线程上进行的似乎是合理的,然而,我正在寻找有关这方面的明确文档。

我想知道的是:这是一个严格定义的地方吗?或者只是当前版本实现方式的一个工件?

至少Timer#scheduleAtFixedRate的Javadocs表明了您所观察到的:

在固定速率执行中,每个执行都是相对于初始执行的调度执行时间进行调度的如果执行由于任何原因(如垃圾收集或其他后台活动)而延迟,则将快速连续执行两次或两次以上以"迎头赶上"。从长远来看,执行频率将恰好是指定周期的倒数(假设Object.wait(long)的系统时钟是准确的)。

最新更新