gpt4 book ai didi

java - 如何在线程上实现有保证的 sleep 时间

转载 作者:搜寻专家 更新时间:2023-11-01 01:32:20 26 4
gpt4 key购买 nike

我要求每 50 毫秒调用一个类方法。我不使用 Thread.sleep 因为它尽可能精确地发生非常重要,而 sleep 只能保证最短时间。基本设置是这样的:

public class ClassA{
public void setup(){
ScheduledExecutorService se = Executors.newScheduledThreadPool(20);
se.scheduleAtFixedRate(this::onCall, 2000, 50, TimeUnit.MILLISECONDS);
}

protected void onCall(Event event) {
// do something
}
}

现在这基本上可以正常工作了。我已将 System.out.println(System.nanoTime) 放入 onCall 中,以检查它是否像我希望的那样被调用。我发现在 100 次调用过程中有 1-5 毫秒的漂移,它会不时地自行纠正。

不幸的是,5 毫秒的漂移对我来说相当大。 1 毫漂移是可以的,但在 5 毫秒时,由于其他对象的状态,它会扰乱我在 onCall 中进行的计算。如果我能让调度程序自动更正,这样如果一个调用晚了 5 毫秒,下一个调用将在 45 毫秒而不是 50 毫秒内发生,那就几乎没问题了。

我的问题是:在 Java 中是否有更精确的方法来实现这一点?目前我能想到的唯一解决方案是每 1ms 调用一个 check 方法并检查时间是否在 50ms 标记处。但是,如果偶然错过精确的 50 毫秒间隔,我需要保持一些逻辑 (49,51)。

谢谢

最佳答案

Can I achieve a guaranteed sleep time on a thread?

抱歉,没有。

在 Java SE JVM 中无法获得可靠、精确的延迟计时。您需要使用 Real time Java在实时操作系统上运行的实现。


以下是普通操作系统上的 Java SE 无法执行此操作的几个原因。

  1. 在某些时候,Java SE JVM 中的 GC 需要“停止世界”。发生这种情况时,没有用户线程可以运行。如果您的计时器在“停止世界”暂停时关闭,则在暂停结束之前无法安排。

  2. JVM 中的线程调度实际上是由主机操作系统完成的。如果系统繁忙,主机操作系统可能会决定在您的应用程序需要时不安排 JVM 的线程。


java.util.Timer.scheduleAtFixedRate 方法可能与您在 Java SE 上获得的一样好。它应该解决长期漂移问题,但您无法摆脱“抖动”。这种抖动很容易达到数百毫秒……甚至几秒。

如果系统繁忙并且操作系统正在抢占或不调度您的线程,自旋锁将无济于事。 (而且用户代码中的自旋锁是浪费...)

关于java - 如何在线程上实现有保证的 sleep 时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38291760/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com