我正在编写一个涉及调用方定义的时间解析的库。在实现中,这个值最终是某个后台线程在执行一些内务处理并再次返回睡眠之前将睡眠的间隔。我允许这个分辨率小到1毫秒,也就是Thread.sleep(1)
。我的直觉是,这可能比忙于等待1毫秒更浪费,也更不精确。如果是这样的话;
- 我应该重新忙碌地等待足够小的时间间隔吗
- 有人知道JVM是否已经在进行优化,而我根本不需要做任何事情吗
这很容易测试:
public class Test {
static int i = 0;
static long[] measurements = new long[0x100];
static void report(long value) {
measurements[i++ & 0xff] = value;
if (i > 10_000) {
for (long m : measurements) {
System.out.println(m);
}
System.exit(0);
}
}
static void sleepyWait() throws Exception {
while (true) {
long before = System.nanoTime();
Thread.sleep(1);
long now = System.nanoTime();
report(now - before);
}
}
static void busyWait() {
while (true) {
long before = System.nanoTime();
long now;
do {
now = System.nanoTime();
} while (before + 1_000_000 >= now);
report(now - before);
}
}
public static void main(String[] args) throws Exception {
busyWait();
}
}
在我的windows系统上运行,这表明busyWait具有微秒级的精度,但完全使用了一个CPU核心。
相比之下,sleepyWait不会导致可测量的CPU负载,但只能达到毫秒级的精度(通常需要2毫秒才能启动,而不是请求的1毫秒(。
因此,至少在windows上,这是精度和CPU使用之间的直接折衷。
同样值得注意的是,除了痴迷于检查时间以全速运行CPU之外,通常还有其他选择。在许多情况下,您可能正在等待其他信号,并且提供专注于基于时间的解析的API可能会将API的用户引向错误的方向。