目标:每隔一段时间执行一些代码。
问题:就性能而言,是否存在显着差异:
while(true) {
execute();
Thread.sleep(10 * 1000);
}
和
executor.scheduleWithFixedDelay(runnableWithoutSleep, 0, 10, TimeUnit.SECONDS);
当然,后一种选择更犹豫不决。然而,我想知道我是否应该开始一项名为“花几天时间重构遗留代码以告别Thread.sleep()”的冒险。
更新: 此代码在超级/超级/超高负载环境中运行。
答案 0 :(得分:10)
你正在处理几十秒钟的睡眠时间。通过改变睡眠选项可能节省的费用可能是纳秒或微秒。
我每次都更喜欢后一种风格,但是如果你拥有前者,而且要改变它会花费你很多,“提高性能”并不是一个特别好的理由。
编辑 re:8000个帖子
8000个线程非常多;我可能会移动到计划执行程序,以便您可以控制系统上的负载量。关于不同唤醒时间的观点需要注意,尽管我认为更大的风险是线程踩踏,所有线程都在沉睡,然后紧密连续醒来并争夺所有系统资源。
我会花时间将这些全部放在一个固定的线程池调度执行器中。只有最多有限资源可用的同时运行(例如,#cores或#IO路径)加上一些可以获取任何slop。这将以延迟为代价为您提供良好的吞吐量。
使用Thread.sleep()
方法很难控制正在发生的事情,并且您可能会失去吞吐量和延迟。
如果您需要更详细的建议,您可能需要更详细地描述您要做的事情。
答案 1 :(得分:2)
有不同的场景,
参考来自here
答案 2 :(得分:1)
由于您没有提及Java版本,因此可能会发生变化。
我从Java的源代码中回忆一下,最重要的区别在于内部编写的内容。
对于 Sun Java 1.6 ,如果您使用第二种方法,本机代码也会引入等待并通知对系统的调用。所以,在某种程度上更有线程效率和CPU友好性。
但是你再次放松了控制,你的代码变得更加难以预测 - 考虑你想要睡10秒钟。
所以,如果你想要更多的可预测性 - 你肯定可以选择1。
另外,在旁注中,在遗留系统中遇到类似这样的事情 - 现在有80%的可能性有更好的方法 - 但是神奇的数字是有原因的(剩下的20%)所以,改变风险自负:)
答案 3 :(得分:0)
您说过您正在“大型...高负载环境”中运行,因此,如果我正确理解您的话,您将有许多此类线程同时处于休眠状态,就像您的代码示例一样。重用线程比杀死并创建一个新线程要花费更少的CPU时间,并且重构可能使您可以重用线程。
您可以使用corePoolSize
大于1的ScheduledThreadPoolExecutor创建线程池,然后在该线程池上调用scheduleWithFixedDelay时,如果有线程可用重用。
此更改可能会降低CPU利用率,因为正在重用线程而不是销毁和创建线程,但是减少的程度将取决于它们正在执行的任务,池中的线程数等。内存使用率也会降低如果某些任务重叠,则关闭,因为一次空闲的线程较少。