Java 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

我有一个在windows系统上运行的程序。用下面的逻辑。我看到线程实际休眠60秒,但时间戳和打印的持续时间是55秒。据我所知,Thread.sleep和System.currentTimeMillis都取决于系统时间。为什么我会看到这种差异

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();
        }
    }
}