Thread.sleep()与Executor.scheduleWithFixedDelay()的区别

30

目标:定时执行特定代码。

问题:在性能方面,以下两种方式是否存在显著差异:

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

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

当然,后者更合适。但是,我想知道是否应该开始一次名为“花费几天时间重构遗留代码以告别Thread.sleep()”的冒险。

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


我认为两者是相同的,scheduleWithFixedDelay 封装了 sleep 调用。 - Subhrajyoti Majumder
1
@Quoi:它们并不完全相同,因为定时执行器可以接受多个计划任务,并在少于任务数量的线程中运行它们。如果您只使用sleep,则必须为每个“计划”的任务拥有一个线程。 - Steven Schlansker
6
你为什么问关于 sleep 操作的性能? - Dan
4
我看到线程转储中的内容是这样的:java.lang.Thread.State: TIMED_WAITING(睡眠)VS java.lang.Thread.State: TIMED_WAITING(停车)。 显然有区别,可能还涉及性能问题。 - rudgirello
4个回答

13

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

我总是更喜欢后者的风格,但如果你使用前者并且更改会花费很多成本,“提高性能”并不是一个特别好的理由。

编辑 关于8000个线程

8000个线程实在太多了;我可能会切换到计划任务执行器,以便您可以控制系统上的负载量。您关于不同唤醒时间的观点值得注意,尽管我认为更大的风险是所有线程都在紧密相继地睡眠和唤醒之后争夺所有系统资源。

我建议将它们全部投入一个固定的线程池计划任务执行器中。仅具有与最受限制的资源(例如,#核心或#IO路径)相同数量的并发运行加上一些用于捡起任何杂项。这将牺牲延迟以获得良好的吞吐量。

使用 Thread.sleep() 方法将非常难以控制正在发生的事情,您可能会在吞吐量和延迟方面失去优势。

如果您需要更详细的建议,您可能必须更详细地描述您正在尝试做什么。


我的担忧是我们有8000个线程,休眠的线程可能会因为优先级太低而延迟执行,可能会引发与垃圾回收相关的问题。 - rudgirello

1
有不同的情况,
1. 定时器创建一个任务队列,该队列会不断更新。当定时器完成后,它可能不会立即被垃圾回收。因此,创建更多的定时器只会在堆上添加更多的对象。Thread.sleep() 只暂停线程,所以内存开销极低。
2. Timer/TimerTask 还考虑了您的任务执行时间,因此它会更准确。并且它能更好地处理多线程问题(如避免死锁等)。
3. 如果您的线程出现异常并被终止,那就是个问题。但是 TimerTask 会照顾到它。无论前一次运行是否失败,它都会运行。
4. TimerTask 的优点在于它更好地表达了您的意图(即代码可读性),并且已经实现了 cancel() 功能。
参考来源:这里

1

由于您没有提到Java版本,所以情况可能会有所改变。

据我回忆,从Java的源代码中可以看出,主要的区别在于内部编写方式的不同。

对于Sun Java 1.6,如果您使用第二种方法,则本地代码还会将wait和notify调用带入系统。因此,在某种程度上更具线程效率和CPU友好性。

但是,您失去了控制权,代码变得更加不可预测-考虑您想要睡眠10秒钟。

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

另外,顺便说一下,在遇到这种情况的旧系统中-80%的机会现在有更好的解决方法-但是魔术数字存在的原因(剩下的20%)是有原因的,因此自行承担风险进行更改:)


0

你说你正在一个“超高负载环境”中运行,如果我理解正确,你有许多这样的线程同时像你的代码示例一样处于睡眠状态。重用线程比杀死和创建新线程需要更少的CPU时间,而重构可能允许您重用线程。

您可以使用ScheduledThreadPoolExecutor创建线程池,并将corePoolSize设置大于1。然后,当您在该线程池上调用scheduleWithFixedDelay时,如果有可用线程,它将被重用。

这种改变可能会降低CPU利用率,因为线程被重用而不是销毁和创建,但减少的程度取决于它们执行的任务、线程池中的线程数量等。如果某些任务重叠,内存使用量也会降低,因为会有更少的线程闲置。


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