Thread.sleep 等待时间超出预期

发布于 2024-11-09 03:20:49 字数 526 浏览 0 评论 0原文

以下代码:

long msBefore = System.currentTimeMillis();
//Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
try
{Thread.sleep(200);
} catch (InterruptedException e){}
System.out.println("Time: " + (System.currentTimeMillis() - msBefore));

打印:

Time: 578
Time: 594
Time: 625
Time: 640
Time: 641
Time: 609
Time: 625
Time: 625
Time: 610
Time: 609
Time: 625
Time: 625
Time: 422
Time: 625
Time: 594
Time: 609
Time: 625
Time: 594
Time: 594
Time: 625

问题出在哪里?

The following code:

long msBefore = System.currentTimeMillis();
//Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
try
{Thread.sleep(200);
} catch (InterruptedException e){}
System.out.println("Time: " + (System.currentTimeMillis() - msBefore));

prints :

Time: 578
Time: 594
Time: 625
Time: 640
Time: 641
Time: 609
Time: 625
Time: 625
Time: 610
Time: 609
Time: 625
Time: 625
Time: 422
Time: 625
Time: 594
Time: 609
Time: 625
Time: 594
Time: 594
Time: 625

Where's the problem??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

决绝 2024-11-16 03:20:49

我要求每秒发送 n 条消息,我认为等待/通知不适合,对吗?

如果您有严格的计时要求,那么您将需要使用 实时 Java 执行。主流的 SE 和 ME Java 实现不适合硬实时应用程序。

您可以使用各种技巧来满足“大多数情况下”的此类要求……但是如果您的应用程序/系统超载,您可能会开始错过所需的消息速率。

真正的问题不是计时器的准确性,而是非实时调度程序不会(也不能)保证在计时器到期后立即调度线程运行。

I have a requirement to send n messages per second, I think wait/notify don't fit, correct?

If you have a hard timing requirement, then you are going to need to use a real-time Java implementation. Mainstream SE and ME Java implementations are not suitable for hard realtime applications.

There are various tricks you can use to meet such requirements "most of the time" ... but if your application / system gets overloaded you are liable start to missing the required message rate.

Th real problem is not the accuracy of the timers, but the fact that a non-realtime scheduler won't (and can't) guarantee to schedule the thread to run as soon as the timer expires.

瞎闹 2024-11-16 03:20:49

这里没有问题。来自javadoc:

受限于系统的准确性和
调度程序。

通常,依赖睡眠间隔是不好的设计,因为它在不同的系统和 JVM 实现上可能有所不同。使用 wait() 和 notification() 代替,或者更好 - 使用 java.util.concurrent 包。

There is no problem here. From javadoc:

subject to the accuracy of system and
schedulers.

Usually, it is bad design to rely on the sleeping interval as it can be different on different systems and JVM implementations. Use wait() and notify() instead, or better - use java.util.concurrent package.

眼泪都笑了 2024-11-16 03:20:49

您没有考虑它花费在处理上的时间。

    try {
        long processingStart = System.currentTimeMillis();

        long processingFinish = System.currentTimeMillis();
        long processTime = 600 - (processingFinish - processingStart);
        Thread.sleep(processTime);

    } catch (InterruptedException ex) {

    }

You're not taking into account the time it spends processing.

    try {
        long processingStart = System.currentTimeMillis();

        long processingFinish = System.currentTimeMillis();
        long processTime = 600 - (processingFinish - processingStart);
        Thread.sleep(processTime);

    } catch (InterruptedException ex) {

    }
美人骨 2024-11-16 03:20:49

如果您确实需要固定消息速率,请实现自旋锁之类的东西。它会消耗单个 CPU 核心,但让你接近。

long nextTime = System.currentTimeMillis() + interval;
while (keepRunning) {
   while (nextTime - System.currentTimeMillis() > 0)
       ;
   sendMessage();
   nextTime += interval;
}

If you really need fixed message rate, implement something like a spin-lock. It will consume single CPU core, but get you close.

long nextTime = System.currentTimeMillis() + interval;
while (keepRunning) {
   while (nextTime - System.currentTimeMillis() > 0)
       ;
   sendMessage();
   nextTime += interval;
}
你没皮卡萌 2024-11-16 03:20:49

我正在与 GLFW 合作并遇到同样的问题,我有一个解决方案。你可以得到你想要的睡眠时间和现实的差异,然后减少睡眠时间。

public void runApp() {
    double begin, end, delta, sleepTime, sleepExtras = 0;

    while (alive) {
        if (appWindow.shouldClose()) break;

        begin = Chronos.currentTime(); // Time in second

        // === RENDER ACTION ===
        appWindow.render();
        // === END RENDER ACTION ===

        glfwPollEvents();

        end        = Chronos.currentTime();
        delta      = end - begin;
        currentFPS = Math.min(1 / delta, lockFPS);
        sleepTime  = Math.max(1.0 / currentFPS - delta - sleepExtras, 0);

        try {
            begin = Chronos.currentTime();
            // IDK why it sleeps with 2 extra milliseconds on my computer =))
            Thread.sleep((long) ((sleepTime) * 1e3));
            end         = Chronos.currentTime();
            delta       = end - begin;
            sleepExtras = delta - sleepTime;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

I'm working with GLFW and get a same problem, I have a solution for this. You can get the difference from sleep time you want and reality and then reduce sleep time.

public void runApp() {
    double begin, end, delta, sleepTime, sleepExtras = 0;

    while (alive) {
        if (appWindow.shouldClose()) break;

        begin = Chronos.currentTime(); // Time in second

        // === RENDER ACTION ===
        appWindow.render();
        // === END RENDER ACTION ===

        glfwPollEvents();

        end        = Chronos.currentTime();
        delta      = end - begin;
        currentFPS = Math.min(1 / delta, lockFPS);
        sleepTime  = Math.max(1.0 / currentFPS - delta - sleepExtras, 0);

        try {
            begin = Chronos.currentTime();
            // IDK why it sleeps with 2 extra milliseconds on my computer =))
            Thread.sleep((long) ((sleepTime) * 1e3));
            end         = Chronos.currentTime();
            delta       = end - begin;
            sleepExtras = delta - sleepTime;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文