Получение точного истекшего времени с использованием Java до миллисекунды

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

Я пытаюсь получить точное время с точностью до миллисекунды на Java. Я использую System.nanoTime () для получения текущего времени и реализую его в следующем коде. Имейте в виду, это был код, который я использовал для проверки его точности.

long startTime = System.nanoTime () / 1000000;
while (true)
{
System.out.println ((System.nanoTime () / 1000000) -startTime);
}

Часть вывода выглядит так.

1110
1112
1112
1113
1114
1118
1120

Первая цифра - это количество секунд, вторая - десятые доли секунды, третья - сотые, а последняя - тысячные. Вы не можете увидеть это здесь, но у меня точность до сотых - никаких пропущенных или повторяющихся чисел. Однако тысячные доли - это далеко не точность. 0 -> 2 -> 2 -> 3 -> 4 -> 8 -> 0. Для того, что я делаю, мне нужна точность до тысячных долей, и из всего, что я прочитал, похоже, что System.nanoTime () должна быть способен обеспечить точность до миллисекунды.

Я что-то делаю не так или есть другой способ получить точность до миллисекунды?


person Antillies    schedule 29.03.2011    source источник
comment
Что заставляет вас думать, что результаты неточны?   -  person Isaac Truett    schedule 29.03.2011
comment
Ваш код не будет выполняться каждый раз за одно и то же количество миллисекунд.   -  person Gilbert Le Blanc    schedule 29.03.2011


Ответы (3)


Здесь есть два фактора.

Во-первых, даже System.nanoTime() не обязательно является действительно точным - он просто использует самые лучшие доступные часы (и не следит за изменениями часов, поэтому никогда не идет назад или не перескакивает вперед).

Во-вторых, ваша Java-программа - не единственная программа, работающая на вашем компьютере, поэтому ваш код (который, по сути, является вызовом собственной функции nanoTime и выводом результата) каждый раз будет занимать разное количество времени. Например, может случиться так, что для одного вывода требуется более полной миллисекунды, а для другого - только половину или меньше.

Попробуйте вывести еще несколько цифр (т.е. разделить на меньшее число), результаты будут полезны для понимания.

person Paŭlo Ebermann    schedule 29.03.2011

После вычитания разделите на 1 миллион и используйте литерал long.

long startTime = System.nanoTime();

while (true)
{
    System.out.println((System.nanoTime() - startTime)/1000000L);
}

Демо (обновлено): http://ideone.com/X5RRa

person Matt Ball    schedule 29.03.2011
comment
Это не изменит того факта, что цикл не гарантированно будет выполняться через регулярные промежутки времени, чего, похоже, он и ожидал. - person Isaac Truett; 29.03.2011
comment
Я предполагаю, что я ожидал, что миллисекунды будут увеличиваться регулярно (0, 1, 2, 3 и т. Д.). Делают десятые и сотые. Вы говорите, что миллисекунды этого не произойдут? - person Antillies; 29.03.2011
comment
@Antillies: вы ожидаете, что цикл будет выполняться ровно один раз в миллисекунду? Почему? - person Matt Ball; 29.03.2011
comment
@ Мэтт: Думаю, у меня создалось впечатление, что цикл будет выполняться очень быстро. Но я полагаю, что из того, что вы говорите, я понимаю, что время, необходимое для выполнения цикла, создает то, что я воспринимаю как неточность. Правильно ли я понимаю вас, что это не неточность, но цикл не может распечатать миллисекунды так быстро, как они возникают, из-за времени, необходимого для выполнения цикла? - person Antillies; 29.03.2011
comment
Спасибо всем за вашу помощь. Думаю, я лучше понимаю, что мне нужно делать сейчас. - person Antillies; 29.03.2011

java.time

Старые классы даты и времени теперь заменены классами java.time.

Классы java.time поддерживают разрешение до наносекунд. Но помните, что фактическое разрешение и точность зависят от аппаратных часов главного компьютера. Таким образом, ваши результаты будут отличаться.

Instant instant = Instant.now();  

2016-01-02T12:34:56.123456789Z

Чтобы уменьшить возможное разрешение наносекунды до миллисекунды, вызовите _ 2_.

Instant instantTruncated = Instant.now().trucatedTo( ChronoUnit.MILLIS );

2016-01-02T12:34:56.123Z

Имейте в виду, что большинство аппаратных часов компьютеров не очень точны с точностью до миллисекунды-микросекунды-наносекунды.


Незначительное примечание: хотя классы java.time поддерживают сохранение наносекундного разрешения, в Java 8 унаследованная реализация _ 4_ ограничен захватом текущего момента, используя только миллисекунды, а не наносекунды. Java 9 содержит свежая реализация _ 5_, поэтому текущий момент может быть записан с разрешением до наносекунды в зависимости от возможностей аппаратного обеспечения часов вашего компьютера и ОС хоста.

person Basil Bourque    schedule 19.09.2016