【问题标题】:Java performance issue with Thread.sleep()Thread.sleep() 的 Java 性能问题
【发布时间】:2010-10-18 03:52:51
【问题描述】:

内联 Java IDE 提示状态,“在循环中调用 Thread.sleep 会导致性能问题。”我在文档的其他地方找不到任何说明。这个声明。

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

【问题讨论】:

  • 也许您可以更改问题以澄清它实际上是来自某些 IDE 的警告......例如“'Invoking ...'可能意味着哪个性能问题?”

标签: java multithreading


【解决方案1】:

循环中的Thread.sleep 本身并不是性能问题,而是通常暗示你做错了什么。

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

仅当您想将线程挂起一段时间时才使用Thread.sleep。如果您想等待某个条件,请不要使用它。

对于这种情况,您应该改用wait/notify 或并发工具包中的一些构造。

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

【讨论】:

  • 感谢您的回复。线程正在通过 TCP 与外部设备通信,等待它开始运行:
  • 协议是,你在运行吗?不,睡觉……你在跑步吗?不,睡觉……你在跑步吗?是的。继续....所以没问题。谢谢!
  • 不要忘记 InterruptedException。
【解决方案2】:

这取决于等待是否依赖于另一个线程完成工作,在这种情况下你应该使用guarded blocks,或者Java 1.6中引入的high level concurrency classes。我最近不得不修复一些使用线程休眠而不是受保护块的CircularByteBuffer 代码。使用以前的方法,无法确保正确的并发性。如果你只是想让线程像游戏一样休眠,在核心游戏循环中暂停执行一段时间,以便线程有良好的执行时间,Thread.sleep(..) 非常好。

【讨论】:

    【解决方案3】:

    这取决于你为什么让它进入睡眠状态以及你运行它的频率。

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

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

    【讨论】:

      【解决方案4】:

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

      1.6。我可以从 Thread.sleep() 获得什么精度?

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

      对于 Sun JDK,据报道 Thread.sleep(1) 在 Windows 上非常精确。对于Linux,它依赖于内核的定时器中断。如果内核使用 HZ=1000(alpha 上的默认值)编译,则报告的精度很好。对于 HZ=100(x86 上的默认值),它通常会休眠 20 毫秒。

      使用 Thread.sleep(millis, nanos) 不会改善结果。在 Sun JDK 中,纳秒值只是四舍五入到最接近的毫秒。 (马蒂亚斯)

      【讨论】:

        【解决方案5】:

        为什么?那是因为上下文切换(操作系统 CPU 调度的一部分)

        怎么样?调用 Thread.sleep(t) 使当前线程从运行队列移动到等待队列。在时间 't' 到达后,当前线程从等待队列移动到就绪队列,然后需要一些时间被 CPU 挑选并运行。

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

        【讨论】:

          【解决方案6】:

          我之前在等待异步进程返回结果时遇到过这个问题。

          Thread.sleep 是多线程场景的问题。它往往会睡过头。这是因为它在内部重新排列其优先级并让给其他长时间运行的进程(线程)。

          一种新方法是使用 ScheduledExecutorService 接口或 java 5 中引入的 ScheduledThreadPoolExecutor。

          参考:http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ScheduledExecutorService.html

          【讨论】:

            【解决方案7】:

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

            在我的例子中,我使用 Thread.sleep() 等待几秒钟,然后再次尝试重新连接到外部进程。我有一个用于此重新连接逻辑的 while 循环,直到它达到最大尝试次数。因此,就我而言, Thread.sleep() 纯粹是出于计时目的,而不是在多线程之间进行协调,这很好。

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

            【讨论】:

              【解决方案8】:

              我建议研究 CountDownLatch 类。网上有很多琐碎的例子。当我刚开始多线程编程时,它们只是替换“sleeping while loop”的门票。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-12-06
                • 2014-08-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多