Java 定时器和 scheduleAtFixedRate + 系统挂起

Posted

技术标签:

【中文标题】Java 定时器和 scheduleAtFixedRate + 系统挂起【英文标题】:Java Timer and scheduleAtFixedRate + System Suspend 【发布时间】:2011-07-30 21:52:38 【问题描述】:

我正在开发一个 Java 程序,并使用 Timer 对象每隔几分钟或几小时运行一次任务。这在正常操作中工作正常,但我在 Mac 上遇到了“睡眠模式”的问题(可能在其他操作系统上,但我还没有尝试过)。

考虑这个代码示例:

//Setup the timer to fire the ping worker (every 3 minutes)
_PingTimer.scheduleAtFixedRate(new TimerTask()
        public void run()
            Program.PingThread = new PingWorker(Settings.Username, Settings.UserHash, true, true);
            Program.PingThread.CheckOpenPort = true;
            Program.SwingExecutor.execute(Program.PingThread);
        
    , 0, 180000);

在正常操作中,这会以足够的精度每 3 分钟触发一次(我不关心确切的秒数或其他任何东西)。这个问题是在计算机休眠几个小时左右之后,它似乎只是用积压的计时器请求来破坏系统。

它似乎在一次运行睡眠期间所有错过的计时器,试图弥补失去的时间。

有什么办法可以防止这种情况发生吗?我尝试使用synchronized 和其他一些线程技术,但这只能确保它们不会同时运行。他们仍然继续一个接一个地运行,直到积压过去。

感谢您提供的任何帮助!

【问题讨论】:

帮不上忙 - 只是用 mac,还是一般睡觉? 【参考方案1】:

你看过API吗?它明确指出以下内容:

在固定利率执行中,每个 执行是相对于 的预定执行时间 初始执​​行。如果执行是 因任何原因延迟(例如 垃圾收集或其他背景 活动),两个或更多的执行将 接二连三地“赶上” 向上。”从长远来看, 执行将完全是 指定期间的倒数 (假设系统时钟底层 Object.wait(long) 是准确的)。

这是您应该考虑使用ScheduledExecutorService 的原因之一。这个link 也可能很有用。

【讨论】:

显然我错过了这个重要的注意事项!感谢您对ScheduledExecutorService 的建议。我正在研究这个,今晚我会逐步完成。 @jocull:没问题,让我知道进展如何! :) 好吧,我试了一下,结果似乎是一样的。但是我刚刚意识到我使用的是scheduleAtFixedRate 而不是scheduleWithFixedDelay。我正在用后者再试一次。 scheduleWithFixedDelay 是票!现在一切似乎都井井有条。再次感谢您! 非常感谢!这也发生在 Windows 上。有一段时间我们想知道为什么从休眠状态唤醒时 CPU 使用率会飙升,直到我们意识到 scheduleWithFixedDelay 会用线程淹没你的 CPU。【参考方案2】:

使用schedule 而不是scheduleAtFixedRate

【讨论】:

schedule 本身不会重新排队吗?

以上是关于Java 定时器和 scheduleAtFixedRate + 系统挂起的主要内容,如果未能解决你的问题,请参考以下文章

Java 定时器和 scheduleAtFixedRate + 系统挂起

如何用java实现一个计时器来定时读取和写入数据库?急!

定时器篇---java.util.TimerTask和quarts

Java定时器Timer和TimerTask

在java中如何让定时器只启动一次?

用java编写一个计数器或计时器