Thread.sleep (миллисекунда) точность

Thread.sleep(500) приостанавливает текущий поток как минимум на 500 миллисекунд, я знаю, что это может быть чуть больше 500, но не меньше. Теперь 1 миллисекунда = 1000000 наносекунд. Я хочу приостановить текущий поток на 500 миллисекунд, т. Е. = 500 * 1000000 наносекунд. Но когда я запускаю следующий код, он иногда спит меньше указанного значения в наносекундах. Почему это? и как спать хотя бы 500*1000000 наносекунд.

long t1=System.nanoTime();
    try{
        Thread.sleep(500);
    }catch(InterruptedException e){}
    long t2=System.nanoTime();

    System.out.println((t2-t1)+" nanoseconds");
    System.out.println((500*1000000-(t2-t1))+" nanoseconds");

иногда вывод

499795328 nanoseconds
204672 nanoseconds

person Faisal Bahadur    schedule 31.12.2015    source источник
comment
Ваша математика неверна, но тем не менее те же результаты (t2-t1)-TimeUnit.MILLISECONDS.toNanos(500) TimeUnit более наглядны.   -  person WalterM    schedule 31.12.2015


Ответы (2)


Я знаю, что это может быть чуть больше 500, но никогда не меньше.

Не знаю, откуда у вас появилась эта идея. Состояние документов вполне ясно, что он будет бездействовать «в течение указанного количества миллисекунд, в зависимости от точности и точности системных таймеров и планировщиков».

Ничто не гарантирует, что продолжительность является абсолютным минимумом.

Если вы хотите приблизиться к идеалу, у вас уже есть половина решения, поскольку вы вычисляете, сколько наносекунд осталось в продолжительности. Чтобы вычислить, сколько еще миллисекунд нужно спать, вы можете разделить нехватку (в данном случае 204672) на тысячу, а затем снова заснуть.

Фактически, вы, вероятно, захотите сделать это в цикле, пока оставшееся время не достигнет нуля. Может работать что-то вроде следующего псевдокода:

def sleepFor (ms):
    baseTime = System.nanoTime()
    remainingTime = ms
    while remainingTime > 0:
        Thread.sleep(remainingTime)
        nowTime = System.nanoTime()
        remainingTime = ms - (nowTime - baseTime) / 1000

Или вы могли бы просто принять тот факт, что достаточно близко достаточно, учитывая, что ваша ошибка составляет около 0,04% (около 400 частей на миллион).

person paxdiablo    schedule 31.12.2015
comment
Возможно, они путают его с другими снами, где время является нижней границей. Например, из libc Linux: функция nanosleep() заставляет вызывающий поток спать в течение времени, указанного в rqtp (фактическое время ожидания может быть больше из-за системных задержек и возможных ограничений разрешения таймера оборудования) . - person John Hascall; 31.12.2015

документация по API говорит, что время

зависит от точности и правильности системных таймеров и планировщиков

Таким образом, точное время, в течение которого он будет находиться в состоянии сна, не определено.
С учетом сказанного логично, что если поток начинает спать в середине миллисекунды, а затем пробуждается в начале указанной миллисекунды, тогда он может спать на 1 миллисекунду меньше, чем хотелось бы.
Если вам требуется точное время, то Thread.sleep, вероятно, является неправильным инструментом, на самом деле любой язык со сборкой мусора, вероятно, является неправильным инструментом.

Один из способов запустить код с более точной задержкой или периодом — использовать ссылку ScheduledExecutorService

person Magnus    schedule 31.12.2015