【问题标题】:Java thread execution order when using Timer and TimerTask使用 Timer 和 TimerTask 时的 Java 线程执行顺序
【发布时间】:2010-07-19 20:07:08
【问题描述】:

我使用 Timer 作为进程中断机制。逻辑流程如下:

T0:在T0创建新的定时器,并安排一个新的定时器任务在T2执行(1秒任务延迟,任务很简单——设置一个标志变量)

T1:在主调用线程,休眠5秒

T2:在定时器线程中,任务执行

T5:睡眠结束

T6:取消计时器和任何计划任务

代码在我的 Windows 和 Ubuntu 开发环境中完美运行。但是当我在我的 SLES 10 构建服务器上运行相同的代码时,日志会指示此执行顺序:

T0:创建定时器和定时器任务在T2执行

T1:主线程休眠 5 秒

T5:主线程唤醒

T6:定时器取消

T7:任务执行

谁能解释为什么会发生这种情况?非常感谢。

【问题讨论】:

  • 您使用什么日志记录机制?可能只是日志没有被正确刷新。
  • 我正在使用 log4j。我正在使用 System.currentTimeMillis 为每个步骤记录时间戳,所以我希望日志输出的顺序不是罪魁祸首。

标签: java multithreading timer


【解决方案1】:

嗯。我很惊讶你看到了这么大的差异(以秒为单位?),但我想你可能会看到从机器到机器、从 jvm 到 jvm 等的不同执行顺序。特别是当 JIT 为你的代码编译时第一次,我倾向于在我的代码中看到大约 100-300 毫秒的延迟(与随后执行相同代码相比),所以也许它在你的代码中更引人注目?

不确定“进程中断机制”是什么意思。你的意思是定时器任务中断了某个线程?

无论如何,我现在可以建议使用System.nanoTime()。 (虽然我认为它不会解释任何事情,但在认真测量时不鼓励使用System.currentTimeMillis())。通常建议将-server 添加到您的 JAVA_OPTS 中,以便您看到 JIT 优化代码时的行为。多次运行代码并进行统计也是非常可取的。

如果我是你,我会先做这些小事,然后使用 CyclicBarrierCountdownLatch 之类的同步器进行调试,看看延迟到底在哪里。

SLES 中的“背景噪音”(活动程度)是什么?也许操作系统非常繁忙或其他什么?

任务的性质是什么?是否与网络/ IO 相关?

【讨论】:

    【解决方案2】:

    原来是时间戳问题。使用 new Date().getTime 而不是 System.currentTimeMillis 会产生预期的执行时间戳顺序。

    感谢所有好主意。

    【讨论】:

      【解决方案3】:

      您应该考虑在任务完成时触发一个事件。这确保了执行顺序。

      【讨论】:

        最近更新 更多