2016-03-29 3 views
0

У меня есть программа, которая работает на системе Windows. С логикой что-то вроде ниже. Я вижу, что Thread активно спит в течение 60 секунд, но отметки времени и продолжительность печати - 55 секунд. Насколько я знаю, как Thread.sleep, так и System.currentTimeMillis зависят от системного времени. Почему я вижу эту разницу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"); 
} 
+0

Я пробовал имитировать это на своем MAC, но я вижу ожидаемый ответ. Я сделал это на своей Mac OS –

+0

Можете ли вы попробовать еще раз? Всегда ли это '55'? –

+0

Не всегда это отличается. Некоторое время он подходит. Я просто хотел понять, что делает Thread.sleep, чтобы быть более точным. –

ответ

1

Thread.sleep вызывает в настоящее время выполняющийся поток спать (временно прекращают выполнение) в течение указанного срока, при условии точности и точности системных таймеров и планировщиков. Нить не теряет права собственности на какие-либо мониторы, а возобновление исполнения будет зависеть от планирования и доступности процессоров, на которых для выполнения потока.

В любом случае вы не можете предположить, что вызов сна будет приостанавливать поток точно за указанный период времени.

+0

Даже это не должно отличаться на 5 секунд.Думаю, даже 5 миллисекунд. Если, jvm impl на окнах действительно плохо или окна действительно плохо. –

+1

Обычно он спит немного дольше, чем требуется, и я никогда не замечал, что это на пять секунд короче. Опыт OPs действительно странный. –

+1

@EricWang, возможно, возможно, 5 миллисекунд в Windows XP ... У него был очень грубый таймер за «System.currentTimeMillis()» –

1

Как сказал @Tagir_Valeev, планировщик окон не так уж и хорош, это одна из основных причин, по которой я думаю.

Другая причина в том, что есть 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 diff, иногда он отличается на 1 миллисекунду (я думаю, 1 миллисекунда просто округляет).

Таким образом, детали logger.info() или System.out.printf() также занимают время. Но всего несколько миллисекунд, никогда не секунд.

Смежные вопросы