Thread.sleep()VS Executor.scheduleWithFixedDelay()
目标:每隔一段时间执行一次代码。
问题:在性能方面,是否存在显着差异:
while(true) { execute(); Thread.sleep(10 * 1000); }
和
executor.scheduleWithFixedDelay(runnableWithoutSleep, 0, 10, TimeUnit.SECONDS);
?
当然,后一种选择更犹豫不决。 然而,我想知道我是否应该开始一项名为“花几天时间重构遗留代码以告别Thread.sleep()”的冒险。
更新:此代码在超级/超级/超高负载环境中运行。
你正在处理几十秒钟的睡眠时间。 通过更改睡眠选项可能节省的费用可能是纳秒或微秒。
我每次都更喜欢后者的风格,但是如果你有前者,而且要改变它会花费你很多,“提高性能”并不是一个特别好的理由。
编辑重新:8000线程
8000线程非常多; 我可能会移动到计划执行程序,以便您可以控制系统上的负载量。 关于不同唤醒时间的观点是需要注意的,尽管我认为更大的风险是线程踩踏,所有线程都在沉睡,然后紧密连续醒来并争夺所有系统资源。
我会花时间将这些全部放在一个固定的线程池预定执行器中。 只有最多有限资源(例如,#cores,或#IO路径)可用的并发运行,以及一些可以获取任何slop。 这将以延迟为代价为您提供良好的吞吐量。
使用Thread.sleep()
方法将很难控制正在发生的事情,并且您可能会失去吞吐量和延迟。
如果您需要更详细的建议,您可能需要更详细地描述您想要做的事情。
有不同的场景,
- Timer创建一个不断更新的任务队列。 Timer完成后,可能不会立即进行垃圾回收。 因此,创建更多Timers只会在堆上添加更多对象。 Thread.sleep()只会暂停线程,因此内存开销会非常低
- Timer / TimerTask还会考虑任务的执行时间,因此它会更准确一些。 它更好地处理multithreading问题(例如避免死锁等)。
- 如果你的线程获得exception并被杀死,那就是一个问题。 但TimerTask会照顾它。 无论先前运行中的故障如何,它都将运行
- TimerTask的优点在于它更好地表达了您的意图(即代码可读性),并且已经实现了cancel()function。
参考文献来自这里
既然你没有提到Java版本,那么事情可能会改变。
我从Java的源代码中回忆一下,最重要的区别在于内部编写的内容。
对于Sun Java 1.6,如果使用第二种方法,本机代码也会引入等待并通知系统调用。 因此,在某种程度上更高的线程效率和CPU友好性。
但是你又失去了控制权,你的代码变得更加难以预测 – 考虑你想要睡10秒钟。
所以,如果你想要更多的可预测性 – 肯定你可以选择1。
此外,在旁注中,在遗留系统中遇到这样的事情 – 现在有80%的可能性有更好的方法 – 但是神奇的数字是有原因的(剩下的20%)所以,改变它个人风险 :)