我在Java中建立了一个计时循环。简单。我避免使用Thread.sleep(),因为我的线程调度开销使不可能进行高分辨率延迟,因此我改用了以下效率极低的循环并获得了更好的结果:

public static void timerBlockingDelayTest()
{
    long DELAY_TARGET = 5;
    long t0, t;

    t0 = System.currentTimeMillis();
    while (System.currentTimeMillis() < t0+DELAY_TARGET) {}
    t = System.currentTimeMillis();

    long offTargetAmt = Math.abs(t-t0-DELAY_TARGET);
    System.out.format("Timer loop was off target by %d milliseconds\n",
            offTargetAmt);
}


我知道的事情是:操作系统不是实时的,线程调度是操作系统的一时兴起,GC可能会导致延迟。

我没有考虑什么?

在我的机器上(Windows 7 x64,i5、2.4GHz),我可以获得的最佳分辨率约为15毫秒。实际上,如果我将DELAY_TARGET设置为15的倍数,则效果会很好。但是,如果目标时间不在15的倍数附近,则上述offTargetAmt通常为〜8(ms)。

我也知道这篇文章:high resolution timer in java

有没有搞错?!我能做的最好的是正负约8毫秒吗?!我只是在寻找“是的”或“否,您没有考虑____”的答案。谢谢

更新:

使用System.nanoTime()似乎有很大的不同。起初我不相信,但是这里是我更新的代码,比较了这两种方法。你自己看。

public static void timerBlockingDelayTest()
{
    long DELAY_TARGET_MS = 5;
    long NS_PER_MS = 1000000;
    long DELAY_TARGET_NS = DELAY_TARGET_MS * NS_PER_MS;
    long t0, t;

    // Using System.currentTimeMillis()
    t0 = System.currentTimeMillis();
    while (System.currentTimeMillis() < t0+DELAY_TARGET_MS) {}
    t = System.currentTimeMillis();
    long msOffTarget = Math.abs(t-t0-DELAY_TARGET_MS);

    // Using System.nanoTime()
    t0 = System.nanoTime();
    while (System.nanoTime() < t0+DELAY_TARGET_NS) {};
    t = System.nanoTime();
    long nsOffTarget = Math.abs(t-t0-DELAY_TARGET_NS);

    // Compare the two methods
    System.out.format("System.currentTimeMillis() method: ");
    System.out.format(" - Off by %d ms (%d ns) \n",
            msOffTarget, msOffTarget*NS_PER_MS);
    System.out.format("System.nanoTime() method:          ");
    System.out.format(" - Off by %d ms (%d ns)\n",
            nsOffTarget/NS_PER_MS, nsOffTarget);
}


这是一个示例输出:

debug:
System.currentTimeMillis() method:  - Off by 11 ms (11000000 ns)
System.nanoTime() method:           - Off by 0 ms (109 ns)
BUILD SUCCESSFUL (total time: 0 seconds)


更新2(希望是最后一个):

咄。仅仅测量量化的或不完美的时间函数的性能有点愚蠢。我的意思是,我实际上是在单独测量currentTimeMillis()的性能,这并不是我做过的最聪明的事情。在意识到这一点之后,我介绍了上述两种方法,并发现nanoTime()确实产生了更好的分辨率。

如果没有分析器,请使用nanoTime()来测量currentTimeMillis()循环的持续时间,如下所示:

public static void timerBlockingDelayTest()
{
    long DELAY_TARGET_MS = 5;
    long NS_PER_MS = 1000000;
    long DELAY_TARGET_NS = DELAY_TARGET_MS * NS_PER_MS;
    long t0ms, t0, t;

    // Using System.currentTimeMillis()
    t0 = System.nanoTime();
    t0ms = System.currentTimeMillis();
    while (System.currentTimeMillis() < t0ms+DELAY_TARGET_MS) {}
    t = System.nanoTime();
    long nsOffTarget1 = Math.abs(t-t0-DELAY_TARGET_NS);

    // Using System.nanoTime()
    t0 = System.nanoTime();
    while (System.nanoTime() < t0+DELAY_TARGET_NS) {};
    t = System.nanoTime();
    long nsOffTarget2 = Math.abs(t-t0-DELAY_TARGET_NS);

    // Compare the two methods
    System.out.format("System.currentTimeMillis() method: ");
    System.out.format(" - Off by %d ms (%d ns)\n",
            nsOffTarget1/NS_PER_MS, nsOffTarget1);
    System.out.format("System.nanoTime() method:          ");
    System.out.format(" - Off by %d ms (%d ns)\n",
            nsOffTarget2/NS_PER_MS, nsOffTarget2);
}


至少以这种方式,我通过相同的参考来测量两个延迟,这只是稍微聪明一点。上面给出了这样的输出:

debug:
System.currentTimeMillis() method:  - Off by 4 ms (4040402 ns)
System.nanoTime() method:           - Off by 0 ms (110 ns)
BUILD SUCCESSFUL (total time: 0 seconds)


结论:使用nanoTime(),祝您生活愉快。

最佳答案

使用System.nanoTime代替。有关nanoTime和currentTimeMillis之间的区别,请参见this answer

关于java - 是否有可能使该Java计时器具有优于〜15 ms的分辨率?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25342872/

10-11 01:30