10

以下代码:

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

问题出在哪里??

4

5 回答 5

8

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

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

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

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

于 2011-05-23T10:19:10.747 回答
7

这里没有问题。来自 javadoc:

取决于系统和调度程序的准确性。

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

于 2011-05-23T10:10:12.363 回答
0

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

    try {
        long processingStart = System.currentTimeMillis();

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

    } catch (InterruptedException ex) {

    }
于 2012-02-26T06:07:02.727 回答
0

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

long nextTime = System.currentTimeMillis() + interval;
while (keepRunning) {
   while (nextTime - System.currentTimeMillis() > 0)
       ;
   sendMessage();
   nextTime += interval;
}
于 2012-06-18T20:37:29.750 回答
0

我正在使用 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();
        }
    }
}
于 2021-10-25T14:14:36.140 回答