2013-10-21 45 views
4

我做Java的过去的试卷,我感到困惑的一个问题如下:当一个线程在它的run()方法执行以下语句Java线程sleep()方法

会发生什么? (选择所有适用的选项。)

sleep(500); 

答:它将停止执行,并在500毫秒后开始执行。

B.这是要停止执行,并开始不早于500毫秒之后再次执行。

C.它会导致编译错误,因为你不能调用run()方法中的睡眠(...)方法。

D.它会导致一个编译器错误,因为睡眠(...)方法不带任何参数。

我选择A,B。但关键答案只有B,是否存在A也可能发生的情况?任何人都可以请澄清,对我?非常感谢。

+1

的Javadoc指出:'使当前执行线程休眠(暂停执行)的指定的毫秒数,取决于系统定时器和调度器的精度和准确度。“取决于你的参考点。但从系统角度来看,至少X时间会在重新启动之前流逝。 –

+1

全部四个答案都是错误的。我已经看到线程睡眠的时间少于请求的毫秒数。这只是一个近似值,真正的睡眠时间可能会多于或少于要求的数量。 –

+0

@DavidWallace也许你指着这个:https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks –

回答

2

JVM不能保证准确500毫秒,但将开始或之后〜500毫秒,因为这将需要开始它的“引擎”回不考虑其他线程阻塞可能延迟一点的任何资源。

阅读:Inside the Hotspot VM: Clocks, Timers and Scheduling Events

编辑:为灰色在评论中指出 - 与其他线程也是一个因素调度,从一个换到另一个可能会花费一些时间。

+0

+1,尽管它更多的是关于与其他线程的调度,然后重新启动它的“引擎”。使用现代操作系统,在大多数情况下,这应该花费微不足道的时间。所以答案是B. – Gray

+0

@格雷 - 我同意。 “引擎”并不是正确的方式,但不知道如何投入它。 –

+0

我想说,如果线程被换出,可能需要一些时间才能交换,但真正的问题是与其他正在运行的线程以及使用CPU的其他OS应用程序竞争。 – Gray

1

根据Javadoc: -

睡眠()

使当前执行线程休眠(暂时停止 执行)指定的毫秒数,受 精度和系统定时器和调度程序的准确性。线程 不会丢失任何监视器的所有权。

因此,它可能是〜500ms的

B.这是要停止执行,并开始不早于500毫秒之后再次执行。

看起来更加突出。

0

这些睡眠时间,但不保证精确的,因为它们通过由基础OS提供的设施的限制。 Option B: Not earlier than 500更正确。

0

不能选择A和B,因为它们是彼此相反的,主要区别:exactly 500 milliseconds laternot earlier than 500 milliseconds later

第一意味着它意味着什么(仅500毫秒),第二意味着它可以睡501或502甚至5000000000

下一个问题 - 为什么B是真的,它不是那么简单的问题,你需要明白硬实时和软实时之间有什么不同,解释所有的原因是相当离谱的,所以简单回答 - 由于许多技术原因,java无法保证您的代码难以实时执行,这就是为什么它声明睡眠将完成not earlier than ...

你可以阅读有关线程调度,优先级,垃圾收集,抢占式多任务 - 所有这些都与此有关

2

我选择A,B。但关键答案只有B,是否存在A也可能发生的情况?任何人都可以请澄清,对我?

是的,根据您的应用程序,您肯定可能会获得500毫秒的睡眠时间,而不是多纳秒。

但是,为什么B更好的答案是,没有任何线程再次运行的保证。您可以拥有一个具有大量CPU绑定线程的应用程序。尽管睡眠线程现在可以运行,但它可能在很长一段时间内没有任何周期。精确的睡眠时间也很大程度上取决于OS线程调度程序的细节和时钟精度。您的应用程序还可能必须与同一系统上的其他应用程序竞争,这可能会延迟其继续执行。

例如,在我的速度极快8xi7 CPU的MacBook Pro这个下面的程序显示了604ms一个最大睡眠:

public class MaxSleep { 

    public static void main(String[] args) throws Exception { 
     final AtomicLong maxSleep = new AtomicLong(0); 
     ExecutorService threadPool = Executors.newCachedThreadPool(); 
     // fork 1000 threads 
     for (int i = 0; i < 1000; i++) { 
      threadPool.submit(new Runnable() { 
       @Override 
       public void run() { 
        for (int i = 0; i < 10; i++) { 
         long total = 0; 
         // spin doing something that eats CPU 
         for (int j = 0; j < 10000000; j++) { 
          total += j; 
         } 
         // this IO is the real time sink though 
         System.out.println("total = " + total); 
         try { 
          long before = System.currentTimeMillis(); 
          Thread.sleep(500); 
          long diff = System.currentTimeMillis() - before; 
          // update the max value 
          while (true) { 
           long max = maxSleep.get(); 
           if (diff <= max) { 
            break; 
           } 
           if (maxSleep.compareAndSet(max, diff)) { 
            break; 
           } 
          } 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      }); 
     } 
     threadPool.shutdown(); 
     threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 
     System.out.println("max sleep ms = " + maxSleep); 
    } 
}