如何将Java线程挂起一小段时间,例如100纳秒?

我知道Thread.sleep()可以使java线程挂起一段时间,比如某些毫秒和某些纳秒。但问题是调用此函数也会导致开销。

例如,如果我希望一个线程挂起 100 纳秒,我调用 Thread.sleep(0, 100)。这个过程的整个成本是invocation_cost + 100纳升,这可能比我想要的要大得多。我怎样才能避免这个问题,并实现我的目的?

我需要这个的原因是我想离线进行模拟。我分析了任务的执行时间;现在,我想通过在同一时间段内挂起线程来模拟此执行时间。

谢谢!


答案 1

睡眠的粒度通常由线程调度程序的中断周期限制。在 Linux 中,此中断周期在最近的内核中通常为 1 毫秒。在 Windows 中,调度程序的中断周期通常约为 10 或 15 毫秒

如果我必须暂停线程的周期少于此值,我通常使用忙碌等待

编辑:我怀疑你会在jrockit + solaris上获得最佳效果。窗户盒子上的数字很糟糕。

@Test
public void testWait(){
    final long INTERVAL = 100;
    long start = System.nanoTime();
    long end=0;
    do{
        end = System.nanoTime();
    }while(start + INTERVAL >= end);
    System.out.println(end - start);
}

答案 2

对于模拟,我不会尝试实时模拟,因为这不会给你可重复的结果。即,您无法测试您的模拟。

相反,我会使用数据驱动的模拟时钟,并尽可能快地运行所有内容。这为您提供了可重复的结果,并允许您比实时更快地进行模拟(例如,速度提高2倍至100倍)


怀疑线程大约需要 10 微秒。尝试在比这更短的时间内挂起线程是没有意义的。

要忙于等待一小段时间,可以尝试。

long start = System.nanoTime();
while(start + delay >= System.nanoTime());

注意:正如@EugeneBeresovsky评论的那样,在您的计算机运行292年后,这可能会溢出,因此您可以选择将其写为

while(System.nanoTime() - start < delay);

相反,对于少于292年的延迟,这将很好。您可以使用 System.currentTimeMillis() 来延长延迟时间。

然而,即使这样也不可靠,因为 System.nanoTime() 在 Centos 5.x 上可能需要高达 300 ns 的时间,因此调用它两次将花费比 100 ns 更长的时间。此外,许多操作系统的分辨率仅为1000 ns(1微秒),因此无论您要寻找的延迟如何,此循环都将等待最多1微秒。

相反,您可以做的是忙于在一个没有优化方式的短循环中等待。

对于100 ns的延迟,我怀疑最好忙于等待您正在等待的任何内容,而不是创建单独的繁忙循环。