Java Thread.sleep和System.currentTimeMillis
我有一个在windows系统上运行的程序。用下面的逻辑。我看到线程实际休眠60秒,但时间戳和打印的持续时间是55秒。据我所知,Thread.sleep和System.currentTimeMillis都取决于系统时间。为什么我会看到这种差异Java Thread.sleep和System.currentTimeMillis,java,multithreading,Java,Multithreading,我有一个在windows系统上运行的程序。用下面的逻辑。我看到线程实际休眠60秒,但时间戳和打印的持续时间是55秒。据我所知,Thread.sleep和System.currentTimeMillis都取决于系统时间。为什么我会看到这种差异 public static void main(String[] args) throws InterruptedException { logger.info("Started"); long start = System.currentTimeM
public static void main(String[] args) throws InterruptedException {
logger.info("Started");
long start = System.currentTimeMillis();
logger.info("No Arguments passed waiting for 60 seconds....");
Thread.sleep(60000);
logger.info("Sleep Duration: " + (System.currentTimeMillis()-start));
logger.info("Ended");
}
sleep导致当前正在执行的线程休眠
(暂时停止执行)在规定期限内,根据
系统计时器和调度程序的精度和准确性。线
不会失去任何监控器的所有权,也不会恢复执行
将取决于调度和所依赖的处理器的可用性
执行线程
在任何情况下,您都不能假设调用sleep将在指定的时间段内暂停线程
sleep导致当前正在执行的线程休眠
(暂时停止执行)在规定期限内,根据
系统计时器和调度程序的精度和准确性。线
不会失去任何监控器的所有权,也不会恢复执行
将取决于调度和所依赖的处理器的可用性
执行线程
在任何情况下,您都不能假设调用sleep会在指定的时间段内暂停线程。正如
@Tagir\u Valeev
所说,您的windows调度程序没有那么好,我想这是一个主要原因
另一个原因是,在两个时间点之间有logger.info()
,这可能需要几毫秒的时间
所以,用下面的方法编写程序可能会使它更准确
SleepAccuracyTest.java:(一个TestNG
类,使用Slf4j
作为记录器)
import org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.testng.Assert;
导入org.testng.annotations.Test;
//测试睡眠的准确性,
公共级SleepAccuracyTest{
public static final int MAX_DIFF=1;//MAX DIFF(毫秒),
专用记录器=LoggerFactory.getLogger(SleepAccuracyTest.class);
专用整数计数器=0;
@测试(调用计数=10,alwaysRun=true)
公开无效测试(){
int=1000;
计数器++;
试一试{
info(“启动[{}]”,计数器);
info(“没有参数在等待{}毫秒…”期间传递);
长启动=System.currentTimeMillis();
线程。睡眠(期间);
long end=System.currentTimeMillis();
长实际持续时间=结束-开始;
长差=实际持续时间-持续时间;
Assert.assertTrue(Math.abs(diff)正如@Tagir_Valeev
所说,您的windows的调度程序不是很好,我想这是一个主要原因
另一个原因是,在两个时间点之间有logger.info()
,这可能需要几毫秒的时间
所以,用下面的方法编写程序可能会使它更准确
SleepAccuracyTest.java:(一个TestNG
类,使用Slf4j
作为记录器)
import org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.testng.Assert;
导入org.testng.annotations.Test;
//测试睡眠的准确性,
公共级SleepAccuracyTest{
public static final int MAX_DIFF=1;//MAX DIFF(毫秒),
专用记录器=LoggerFactory.getLogger(SleepAccuracyTest.class);
专用整数计数器=0;
@测试(调用计数=10,alwaysRun=true)
公开无效测试(){
int=1000;
计数器++;
试一试{
info(“启动[{}]”,计数器);
info(“没有参数在等待{}毫秒…”期间传递);
长启动=System.currentTimeMillis();
线程。睡眠(期间);
long end=System.currentTimeMillis();
长实际持续时间=结束-开始;
长差=实际持续时间-持续时间;
Assert.assertTrue(Math.abs(diff)我试着在我的MAC上模拟这个,但我看到了一个预期的答案。我在我的MAC上模拟了它。你可以再试一次吗?它总是55
?不总是不同。有时它会匹配。我只是想了解Thread.sleep做了些什么来更准确。@Vikasmadhusdana,可能你的计算机会将系统时间与intern同步et服务器?通常不是通过立即跳转,而是通过逐渐改变来执行(这样大多数程序不会变得疯狂)。检查此项并禁用网络时间同步。如果我的猜测是正确的,那么实际上睡眠
更不准确,但是系统.currentTimeMillis()
差别不是。你是在虚拟机上运行吗?我试着在我的MAC上模拟这个,但我看到了一个预期的答案。我在我的MAC上做了,然后你再试一次?它总是55
?不总是不同的。有时它匹配。我只是想了解Thread.sleep做什么来更准确。@Vikasmadhusdana,p很有可能你的计算机会将系统时间与internet服务器同步?通常不是通过立即跳转,而是通过逐渐改变来执行(这样大多数程序不会变得疯狂)。检查此项并禁用网络时间同步。如果我的猜测是正确的,那么实际上睡眠
更不准确,但系统。currentTimeMillis()
差别不是。你是在虚拟机上运行吗?即使这样,也不应该相差5秒。我想即使是5毫秒也是不好的。除非windows上的jvm impl真的很差或者windows真的很差。通常它的睡眠时间比请求的要长一点,而且我从未注意到它比请求的短5秒。OPs体验是我ndeed奇怪。@EricWang,在Windows XP上可能有5毫秒的时间…它在系统后面的计时器非常粗糙。currentTimeMillis()
@TagirValeev我做了一个小测试,并添加了一个answ
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;
// test sleep accuracy,
public class SleepAccuracyTest {
public static final int MAX_DIFF = 1; // max diff in milliseconds,
private Logger logger = LoggerFactory.getLogger(SleepAccuracyTest.class);
private int counter = 0;
@Test(invocationCount = 10, alwaysRun = true)
public void testIt() {
int during = 1000;
counter++;
try {
logger.info("Started [{}]", counter);
logger.info("No Arguments passed waiting for {} milliseconds...", during);
long start = System.currentTimeMillis();
Thread.sleep(during);
long end = System.currentTimeMillis();
long actualDuring = end - start;
long diff = actualDuring - during;
Assert.assertTrue(Math.abs(diff) <= MAX_DIFF);
logger.info("Expected during: {}, actual duration: {}, diff: {}", during, actualDuring, diff);
logger.info("Ended\n");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}