在Windows上为Java准确hibernate
有没有人知道一个库,它提供了一个Thread.sleep()Java的错误不超过1-2毫秒?
我尝试了睡眠,错误测量和BusyWait的混合,但我不能在不同的Windows机器上得到这个可靠的。
如果实现可用于Linux和MacOS,则它可以是本地实现。
编辑链接尼克提供( http://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks )是一个非常好的资源来理解各种定时器/睡眠/时钟java的问题。
为了改善睡眠粒度,您可以从这个Thread.sleep页面中尝试以下内容。
与Windows下的Thread.sleep()的错误
如果时机对于你的应用程序是至关重要的,那么一个简单而实用的方法可以避免这些错误,就是在应用程序的整个持续时间内保持守护线程的运行,这个守护进程只需要几毫秒的时间(Long.MAX_VALUE就可以)。 这样,每次调用应用程序时,中断周期就会被设置一次,最小化对系统时钟的影响,即使默认中断周期不是15ms,睡眠粒度也会设置为1ms。
该页面还提到,它导致系统范围的Windows更改,可能会导致用户的时钟运行速度快由于这个错误 。
编辑
有关这方面的更多信息可以在这里find ,并附上Sun的相关错误报告 。
这是大约5个月的时间,但可能对读这个问题的人有用。 我发现java.util.concurrent.locks.LockSupport.parkNanos()
做法与Thread.sleep()
相同,但是在理论上具有纳秒级精度,并且在实践中比Thread.sleep()
好得多。 这当然取决于你正在使用的Java运行时,所以YMMV。
看看: LockSupport.parkNanos
(我在Sun的Linux的1.6.0_16-b01 VM上对此进行了validation)
不幸的是,从Java 6开始,Windows OS上的所有与睡眠有关的方法[包括LockSupport.awaitNanos()]都基于毫秒,正如上面几位人员所提到的。
计算精确区间的一种方法是“自旋产量”。 方法System.nanoTime()给你相当精确的相对时间计数器。 这个调用的成本取决于你的硬件,并在某处2000-50纳米。
build议替代Thread.sleep():
public static void sleepNanos (long nanoDuration) throws InterruptedException { final long end = System.nanoTime() + nanoDuration; long timeLeft = nanoDuration; do { if (timeLeft > SLEEP_PRECISION) Thread.sleep (1); else if (timeLeft > SPIN_YIELD_PRECISION) Thread.yield(); timeLeft = end - System.nanoTime(); } while (timeLeft > 0); }
这种方法有一个缺点 – 在等待命中CPU核心的最后2-3毫秒。 请注意,sleep()/ yield()将与其他线程/进程共享。 如果你愿意妥协一点CPU,这给你非常准确的睡眠 。
在正常的代码中使用Thread.sleep()
没有什么好的理由 – 它几乎总是表示一个糟糕的devise。 最重要的是,没有保证线程将在指定的时间后继续执行,因为Thread.sleep()
的语义只是在给定的时间内停止执行,而不是在经过该时间段后立即继续执行。
所以,虽然我不知道你试图达到什么目的,但我相信你应该使用一个计时器来代替。
JDK提供了Timer类。
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Timer.html
阅读文档清楚地表明,除了使这个泛化框架的工作外,它并没有比调用Object.wait(timeout)更复杂:
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#wait(long);
所以,你可以削减追逐一个只使用Object#等待自己。
除了这些考虑之外,事实仍然是JVM不能保证跨平台的时间准确性。 (阅读http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#currentTimeMillis(); )上的文档
如果您想要在您的平台上实现最高的时序精度,我认为您需要尝试一种折衷解决scheme,将定时器和繁忙轮询结合起来。 有效对象#wait(1) – >系统#nanoTime – >计算delta – > [如果需要,循环]。
如果你愿意推出自己的JNI,那么它几乎可以为平台特定的解决scheme开放。 我对Window的内部机制并不了解,但显然如果主机操作系统确实提供了足够准确的实时定时器服务,那么设置timerRequest(timedelta,callback)本机库的准系统结构就不应该超出范围。
Long.MAX_VALUE hack是工作解决scheme。
我尝试了Object.wait(int milis)来replaceThread.sleep,但发现Object.wait和Thread.sleep(在Windows下是10ms)一样精确。 没有破解,这两种方法都不适合任何animation
使用当前线程上的一个Thread::join
覆盖 。 您指定要等待的毫秒数(和纳秒)。
你可以尝试使用新的并发库。 就像是:
private static final BlockingQueue SLEEPER = new ArrayBlockingQueue(1); public static void main(String... args) throws InterruptedException { for(int i=0;i<100;i++) { long start = System.nanoTime(); SLEEPER.poll(2, TimeUnit.MILLISECONDS); long time = System.nanoTime() - start; System.out.printf("Sleep %5.1f%n", time/1e6); } }
这睡在2.6和2.8毫秒之间。
听起来像你需要一个实时Java的实现 。