Java 为什么从无限循环切换到TimerTask会导致CPU使用率下降?

Java 为什么从无限循环切换到TimerTask会导致CPU使用率下降?,java,multithreading,cpu,timertask,Java,Multithreading,Cpu,Timertask,我编写了一个守护进程,其结构如下: while( true ) { // do some stuff Thread.sleep( 1000 ); } 我注意到它使用了大量的CPU—高达100%。几个月来,我的生产服务器上都有一个类似的守护进程,它有相同的CPU问题 昨天我重构了代码以供使用。我立刻注意到,我的开发设备上的CPU使用量已经减少了。所以我决定部署到生产环境中,并使用Munin进行双重检查。以下是图表: 有两点: 除了JVM,生产服务器上绝对没有其他任何东西在运行 没有

我编写了一个守护进程,其结构如下:

while( true ) {
  // do some stuff
  Thread.sleep( 1000 );
}
我注意到它使用了大量的CPU—高达100%。几个月来,我的生产服务器上都有一个类似的守护进程,它有相同的CPU问题

昨天我重构了代码以供使用。我立刻注意到,我的开发设备上的CPU使用量已经减少了。所以我决定部署到生产环境中,并使用Munin进行双重检查。以下是图表:

有两点:

  • 除了JVM,生产服务器上绝对没有其他任何东西在运行
  • 没有其他应用程序线程正在运行
  • 它肯定是以正确的周期间隔执行旧式代码——每次线程执行时,我都会写入日志

那么:为什么Thread.sleep与TimerTask相比效率如此低下?

我可以想到三种可能性:

  • 有大量线程在执行此操作,并且它们一直在切换上下文。使用计时器意味着只有一个线程。另一方面,这意味着您一次只能执行一个任务
  • 您有一个
    继续语句,因此即使循环的主体工作执行得不是很频繁,也会有一些问题。很难说没有看到更具体的代码
  • 您的JVM/OS组合已损坏。诚然,这似乎不太可能

一个简单的循环只需重复执行
Thread.sleep(1000)
应该非常便宜——这也应该很容易验证。

比较处理器、线程和计时器任务的速度。timertask是一个较慢的线程(要慢得多)。

您能否生成一个简短但完整的程序来演示相同的效果?你有多少个线程在做这个?好主意。稍后我将尝试收集一些东西..sleep()将同步对象锁定。那么,也许答案是TimerTask使用.wait()来代替?我不确定,但不得不这么做try@biovamp这也是我要走的路,但我对Java还不够了解,不能确定。现在我需要在继续之前仔细检查我自己的应用程序逻辑。TimerTask实际上使用了
wait()
。查看
mainLoop
了解
queue.wait(executionTime-currentTime)
我一直想知道在这样的情况下,中断异常(也被吞没)的退化情况的可能性。。。不知道这是否可能,或者只是我多年来一直怀有的一些毫无根据的妄想症。@pst:这又回到了线程的开始实际被执行的频率——当然还有
InterruptedException
是否被吞没了。当OP有一个重编案例时,这将是方便的地方。@Jon Skeet:两件事。首先,我检查了我的旧版本,并添加了更多的日志记录,以再次检查是否存在continue语句或其他奇怪的情况。当然,Thread.sleep()运行正确,CPU使用率仍然和以前一样高。我还编写了一个6行Java类,它与我的主应用程序隔离,并带有一个while(true)循环,如上所述,运行良好,几乎没有CPU使用。因此,它指向了JVM/代码中其他地方的一个问题。至少在我的while()循环中没有进行锁定/同步。还有什么会影响线程性能的吗?@robw:只有其他线程。。。是不是有别的东西在你不知情的情况下启动了一个线程?我会复制一份你的代码,然后开始破解它,逐渐删除越来越多的代码,直到问题消失。例如,如果保留循环之前发生的其余代码,然后将循环更改为睡眠,这是否仍然显示问题?好的-因此在while(true)版本中,我删除了while()循环中除Thread.sleep(1000)和System.out.println()之外的所有其他内容。仍然是同样的超高CPU使用率。将它切换到TimerTask,它几乎降为零。奇怪。我并不急于弄清这一点,因为就我的目的而言,使用TimerTask工作得很好,但它肯定是一个有趣的问题。谢谢你的建议。