Java中使用Thread.sleep()存在性能问题

23

内联Java IDE提示:"在循环中调用Thread.sleep可能会导致性能问题。" 我在文档的其他地方找不到对此说明。

为什么?如何解决?还有没有其他方法可以延迟线程的执行?


也许你可以修改问题,澄清它实际上是来自某个IDE的警告,比如“‘调用…’可能指的是哪个性能问题?” - Volker Stolz
8个回答

36

在循环中使用Thread.sleep本身并不是一个性能问题,但通常这是在暗示您正在做一些错误的事情。

while(! goodToGoOnNow()) {
   Thread.sleep(1000);
}

如果您想暂停线程一定时间,请使用Thread.sleep。但不要在等待某个条件的情况下使用它。

在这种情况下,你应该使用wait/notify或者并发工具包中的某些构造函数。

只有在等待当前JVM外部的条件时(例如等待另一个进程写入文件),才应该使用带有Thread.sleep的轮询。


感谢回复。该线程正在通过TCP与外部设备通信,等待其开始运行: - fcw
协议是,你在运行吗?不是。休眠......你在运行吗?不是。休眠...你在运行吗?是的。继续......所以没有问题。谢谢! - fcw
不要忘记InterruptedException。 - Andrew S

6
这取决于等待是否依赖于其他线程完成工作,如果是这样的话,您应该使用Java 1.6中引入的guarded blocks高级并发类。最近,我不得不修复一些使用Thread.sleep而不是guarded blocks的CircularByteBuffer代码。使用以前的方法,无法确保适当的并发性。如果您只想让线程像游戏一样睡眠,在核心游戏循环中暂停执行一段时间,以便其他线程有良好的执行周期,那么Thread.sleep(..)就可以了。

5

这取决于你为什么要让它休眠以及你运行它的频率。

我可以想到几种不同情况下可能适用的替代方案:

  • 让线程死亡,稍后再启动一个新线程(创建线程也很昂贵)
  • 使用Thread.join()等待另一个线程死亡
  • 使用Thread.yield()允许另一个线程运行
  • 让线程运行但将其设置为较低优先级
  • 使用wait()和notify()

3

http://www.jsresources.org/faq_performance.html

1.6. Thread.sleep()的精度是多少?

短时间睡眠的根本问题在于调用sleep会结束当前的调度时间片。只有在所有其他线程/进程完成后,调用才能返回。

对于Sun JDK,在Windows上报告Thread.sleep(1)相当精确。对于Linux,它取决于内核的计时器中断。如果内核使用HZ=1000(alpha的默认值),则精度被认为是良好的。对于HZ=100(x86的默认值),它通常会休眠20毫秒。

使用Thread.sleep(millis, nanos)不会改善结果。在Sun JDK中,纳秒值仅舍入到最近的毫秒。(Matthias)


2

为什么?这是由于上下文切换(操作系统CPU调度的一部分)。

如何解决?调用Thread.sleep(t)会使当前线程从运行队列移动到等待队列。当时间't'到达时,当前线程从等待队列移动到就绪队列,然后需要一些时间才能被CPU选中并运行。

解决方案:在循环的10次迭代中调用Thread.sleep(t*10);而不是调用Thread.Sleep(t)。


1

1

这可能不是问题,这取决于情况。

在我的情况下,我使用Thread.sleep()等待几秒钟,然后重新连接到外部进程。我有一个while循环来执行重新连接逻辑,直到达到最大尝试次数。所以在我的情况下,Thread.sleep()纯粹是为了计时目的,而不是协调多线程,这是完全可以的。

您可以配置您的IDE以确定如何处理此警告。


0
我建议研究一下CountDownLatch类。网上有很多简单的例子。当我刚开始进行多线程编程时,它们正好可以替代“睡眠while循环”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接