我正在做一篇过去的Java考试试卷,我对下面列出的一个问题感到困惑:
当线程在run()方法中执行以下语句时会发生什么? (选择所有适用的选项。)
sleep(500);
一个。它将停止执行,并在500毫秒后开始执行。
B中。它将停止执行,并在500毫秒之后再次开始执行。
℃。它会导致编译器错误,因为你无法在run()方法中调用sleep(...)方法。
d。它会导致编译器错误,因为sleep(...)方法不接受任何参数。
我选择A,B。但关键答案只是B,是否存在A也可能发生的情况?有人可以请我澄清一下吗?非常感谢。
答案 0 :(得分:2)
JVM不能保证正好500毫秒,但它会在~500毫秒或之后启动,因为它需要启动它的'引擎',因为没有其他线程阻止任何可能会延迟一点的资源。
阅读:Inside the Hotspot VM: Clocks, Timers and Scheduling Events
编辑正如Gray在评论中指出的那样 - 与其他线程的调度也是一个因素,从一个到另一个的交换可能需要一些时间。
答案 1 :(得分:2)
我选择A,B。但关键答案只是B,是否存在A也可能发生的情况?有人可以请我澄清一下吗?
是的,根据您的应用,您当然可能会获得500毫秒的睡眠时间,而不是更多的纳秒时间。
然而,B
更好的答案是,无法保证何时再次运行任何线程。您可以拥有一个具有大量CPU绑定线程的应用程序。即使睡眠线程现在能够运行,它也可能在相当长的一段时间内没有任何周期。精确的睡眠时间也很大程度上取决于OS线程调度程序的详细信息和时钟精度。您的应用程序还可能必须与同一系统上的其他应用程序竞争,这可能会延迟其继续执行。
例如,我的极速8xi7 CPU Macbook Pro上的以下程序显示最大睡眠时间为604毫秒:
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);
}
}
答案 2 :(得分:1)
根据Javadoc: -
<强>睡眠()强>
导致当前正在执行的线程进入休眠状态(暂时停止 执行)指定的毫秒数,受制于 系统定时器和调度程序的精度和准确性。线程 不会失去任何监视器的所有权。
所以它可能是~500ms
B中。它将停止执行,并在500毫秒之后再次开始执行。
看起来更加突出。
答案 3 :(得分:0)
这些睡眠时间不能保证精确,因为它们受底层操作系统提供的设施限制。 Option B: Not earlier than 500
更正确。
答案 4 :(得分:0)
您无法选择A和B,因为它们彼此相反,主要区别为:exactly 500 milliseconds later
和not earlier than 500 milliseconds later
首先意味着它的意思(仅500毫秒),第二意味着它可以睡501或502甚至50000000000000
下一个问题 - 为什么B是真的,不是那么简单的问题,你需要了解硬实时和软实时之间有什么不同,并且解释所有原因是相当偏离主题的,所以简单回答 - 因为许多技术原因java无法保证您的代码难以实时执行,这就是为什么它表示睡眠将完成not earlier than ...
你可以阅读有关线程调度,优先级,垃圾收集,抢占式多任务处理 - 所有这些都与此相关
答案 5 :(得分:0)
如您所知,Thread 中有两个非常密切相关的状态:Running 和 Runnable。
因此,每当您调用 sleep 方法时,它仅保证代码的执行由它运行的线程在参数中的指定毫秒内暂停(例如,threadRef.sleep(300); 中的 300 毫秒)。一旦定义的时间过去,它就会回到Runnable状态(意味着回到Available State以被Thread Schedular拾取)。
因此,不能保证您的剩余代码会在 sleep 方法完成后立即开始执行。