Thread.sleep() VS Executor.scheduleWithFixedDelay()

目标:每隔一段时间执行一次特定代码。

问:在性能方面,以下两者之间是否存在显著差异:

while(true) {
    execute();
    Thread.sleep(10 * 1000);
}

executor.scheduleWithFixedDelay(runnableWithoutSleep, 0, 10, TimeUnit.SECONDS);

?

当然,后一种选择更符合犹太教标准。然而,我想知道我是否应该开始一个名为“花几天时间重构遗留代码以告别Thread.sleep()”的冒险。

更新:此代码在超级/兆/超高负载环境中运行。


答案 1

您正在处理以几十秒为单位的睡眠时间。通过在此处更改睡眠选项可能节省的费用可能是纳秒或微秒。

我每次都更喜欢后一种风格,但是如果你有前者,并且改变它会花费你很多,那么“提高性能”并不是一个特别好的理由。

编辑回复:8000线程

8000个线程是一个可怕的数字;我可能会移动到计划的执行程序,以便您可以控制系统上的负载量。您关于不同的唤醒时间的观点是需要注意的,尽管我认为更大的风险是线程的踩踏,这些线程都处于睡眠状态,然后连续醒来并争夺所有系统资源。

我会花时间把这些都放在一个固定的线程池调度执行器中。只有同时运行的数量与最有限的资源(例如,# 核心或#IO路径)的可用数量一样多,再加上一些来拾取任何倾斜。这将以延迟为代价为您提供良好的吞吐量。

使用该方法将很难控制正在发生的事情,并且您可能会同时损失吞吐量延迟。Thread.sleep()

如果您需要更详细的建议,则可能需要更详细地描述您要执行的操作。


答案 2

由于您没有提到Java版本,因此,事情可能会发生变化。

正如我从Java的源代码中回忆的那样,主要区别在于内部编写的方式。

对于 Sun Java 1.6,如果使用第二种方法,则本机代码还会引入对系统的等待和通知调用。因此,在某种程度上,线程效率更高,CPU友好。

但是,再一次,你放松了控制,它对你的代码变得更加不可预测 - 考虑你想睡10秒钟。

因此,如果您想要更高的可预测性 - 当然可以使用选项1。

另外,在遗留系统中,当你遇到这样的事情时 - 80%的可能性现在有更好的方法来做到这一点 - 但是神奇的数字是有原因的(其余的20%),所以,改变它的风险自负:)