Java ScheduledExecutorService - 需要有关实时性能问题的建议

时间:2012-02-02 22:20:45

标签: java multithreading thread-safety real-time task

我创建了一个多线程应用程序,它使用相同的ScheduledExecutorService(方法scheduleAtFixedRate和10个线程的固定线程池)执行不同的任务。但是,除了一个主要任务之外的所有线程(不要与主线程混淆!)大部分时间都处于睡眠状态,直到有用户输入为止。主任务和其他(用户输入)线程之间共享的数据受同步块中的锁定对象的保护。

主要任务以相当大的频率执行重新执行任务,例如25 Hz(即40 ms的周期),并且此任务及时执行非常重要。通常情况也是如此,但不幸的是并非总是如此。其他“漂亮”的应用程序也在同一台计算机上运行(Linux OP),但CPU <&lt; <100%。

在60分钟的测量期间(即90000个样本),在大约50个案例中,两个连续样本之间的实际周期> = 60毫秒,并且在大约30个这样的周期中超过100毫秒,在几个非常糟糕的情况下案件(时间上彼此相当接近,大约为秒),周期为1000至2300毫秒。测量期间未给出用户输入。查看数据日志,似乎很明显某些事情阻止了执行程序在这些时间间隔内完成其工作,因为它们通常后跟Executor的“赶上”,即在2或3 ms内来自应用程序的多个日志。

我在每次执行任务时都尝试过定期垃圾收集,但(至少从短期来看)它似乎只会让事情变得更糟。我还测量了任务的执行时间。它主要是大约1毫秒,它不应该导致执行程序崩溃(或应该吗?)。这里也是偏差,偶尔大约为100毫秒,但它们可以解释不到50%的延迟。我试过寻找TaskRejectedExceptions,一无所获。

所以我现在的问题基本上是:随着时间的推移,我对ScheduledExecutorService有什么期望?这可能是一个线程问题,尽管事实上在这些情况下只应运行主要任务吗?什么可能导致ScheduledExecutor暂时停止执行,只是用它的“追赶”数据泛洪日志,有没有任何方法来控制这种恼人的行为?这可能与我的JVM只是一个没有实时优先级功能的普通JVM有关吗?关于从哪里开始挖掘的任何帮助,想法或理论都是真正的赞赏!

2 个答案:

答案 0 :(得分:0)

根据计时器documentation,您的情况似乎完全正常:

  

在固定速率执行中,每次执行都是相对于初始执行的预定执行时间进行调度的。如果由于任何原因(例如垃圾收集或其他后台活动)延迟执行,则会快速连续执行两次或更多次执行以“赶上”。从长远来看,执行频率将完全是指定时间段的倒数(假设Object.wait(long)下的系统时钟是准确的)。

事实上,scheduleAtFixedRate()不能保证执行将在它应该启动时准确启动,而只能保证长时间运行的频率。 实际上,我不确定是否有办法使用Java来实现这一目标。

答案 1 :(得分:0)

一些注意事项:

  • 调用垃圾收集器并不能保证收集的方式与您想象的完全相同。来自Java doc:
  

调用此方法表明Java虚拟机消耗   努力回收未使用的物体以制造记忆   它们目前可以快速重复使用。

这里的关键是建议。永远不要指望它完全按照您的预期运行。你也不能期望它能阻止实际的系统垃圾收集在另一个时间运行。

  • 计划了线程,但仍然需要按计划实际执行它们。您的处理器使用率低于100%并不意味着它必须能够执行另一个线程。一般而言,在未完全从头开始编写的环境中期望高度准确的线程实时执行可能不会产生预期的结果。