Thread.sleep和System.currentTimeMillis

时间:2016-03-29 06:04:57

标签: java multithreading

我有一个在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");
 }

2 个答案:

答案 0 :(得分:1)

  

Thread.sleep导致当前正在执行的线程进入休眠状态   (暂时停止执行)指定的持续时间,但须遵守   系统定时器和调度程序的精度和准确性。线程   不会失去任何监视器的所有权,并恢复执行   将取决于调度和处理器的可用性   执行线程。

在任何情况下,您都不能假设调用sleep会在指定的时间段内暂停该线程。

答案 1 :(得分:1)

正如@Tagir_Valeev所说,你的Windows调度程序并不是那么好,这是我猜的一个主要原因。

另一个原因是,在2个时间点之间有logger.info(),可能需要几毫秒。

因此,按照以下方式编写程序可能会使其更准确。

SleepAccuracyTest.java:一个TestNG班级,使用Slf4j作为记录器

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

测试结果:

在我的机器上( 64bit linux-3.16,Java8,4 cpu ):

  • 运行代码时,它有1~6毫秒差异,
  • 当我运行上面的代码时,大多数情况下它有0差异,有时差异为1毫秒(我猜1毫秒只是一个圆整)。

因此,logger.info()System.out.printf()部分也需要时间。 但只有几毫秒,从不秒。