Вызов _ 1_ и его современная замена Instant.now
фиксируют текущий момент, сообщаемый ОС хоста и базовым оборудованием часов компьютера. Документ Javadoc и исходный код обещают часы, «основанные на наилучших доступных системных часах».
Итак, нет, нельзя прыгать в будущее. Каждый раз, когда вы вызываете любой из этих методов, вы фиксируете текущий момент.
Однако вы можете увидеть иллюзию прыжка в будущее. Это может произойти по следующим причинам:
- планирование потоков
- сброс часов
- поддельные часы
Планирование потоков
Эта иллюзия может возникнуть из-за того, что происходит после захвата текущего момента. Через долю секунды после захвата текущего момента выполнение этого потока может быть приостановлено. Другой поток может затем захватить более поздний момент и продолжить сообщать об этом моменте. В конце концов, этот первый поток возобновляется и сообщает о своем ранее зафиксированном моменте, но обратите внимание, как сообщение об этом моменте происходит позже.
Возьмите этот пример кода.
package work.basil.example;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TellTime
{
public static void main ( String[] args )
{
TellTime app = new TellTime();
app.demo();
}
private void demo ( )
{
ExecutorService executorService = Executors.newCachedThreadPool();
int countThreads = 15;
List < Callable < Object > > tasks = new ArrayList <>( countThreads );
for ( int i = 0 ; i < countThreads ; i++ )
{
Runnable tellTimeRunnable = ( ) -> System.out.println( Instant.now() );
tasks.add( Executors.callable( tellTimeRunnable ) );
}
try
{
List < Future < Object > > list = executorService.invokeAll( tasks );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
}
В самый первый раз, когда я запустил этот код, я обнаружил такой скачок в последних двух строках вывода. 4-я строка показывает момент раньше, чем 3-я. Пятая строка показывает момент даже раньше.
2020-11-23T01:07:34.305318Z
2020-11-23T01:07:34.305569Z
2020-11-23T01:07:34.305770Z
2020-11-23T01:07:34.305746Z
2020-11-23T01:07:34.305434Z
В моем случае вызовы System.out.println
задерживались в выполнении, поэтому о некоторых более ранних моментах сообщалось позже. Точно так же я подозреваю, что в вашем случае процесс регистрации ваших захваченных моментов включал в себя различные задержки, так что некоторые более ранние моменты были зарегистрированы позже.
Сброс часов
Как указывает Стивен С в комментариях ниже компьютеры часто настраиваются на автоматическую настройку аппаратных часов на основе информации с сервера времени. Аппаратные часы на многих компьютерах менее точны, чем вы можете себе представить. Таким образом, часы главного компьютера вполне могут быть сброшены на более раннее или более позднее время дня, чтобы скорректировать дрейф отслеживания времени.
Имейте в виду, что некоторые компьютеры сбрасывают свои часы обратно к точке эталонной эпохи, например 1970 г. -01-01 00: 00Z при загрузке с неисправным или разряженным аккумулятором / конденсатором, поддерживающим аппаратные часы. Этот эталонный момент эпохи может указываться как текущий момент, пока компьютер не получит возможность связаться с сервером времени.
Или какой-нибудь человек может вручную настроить текущую дату и время на компьютерных часах. :-(
Ваш код может фиксировать текущий момент по обе стороны от этой настройки часов. Теперь может показаться, что более позднее событие произошло раньше.
Поддельные часы
В java.time такие вызовы, как Instant.now
, обращаются к назначенному в данный момент _ 7_ реализация. Под текущим назначением я обращаюсь к тому факту, что в java.time объект Clock
по умолчанию может быть переопределен. Обычно это делается только для целей тестирования. Различные объекты Clock
могут сообщать фиксированный момент, сдвинутый момент или может сообщить с измененный ритм.
Так что имейте в виду, что альтернативный Clock
может намеренно указать другое время, если в вашем тестовом коде указан альтернативный Clock
объект. По умолчанию вы всегда получаете текущий момент времени выполнения вызова метода.
Вывод
Здесь есть важный вывод: нельзя полностью доверять учету времени. Текущий момент может быть неправильно записан, и отчет о захваченных моментах может быть неупорядоченным.
Поэтому при отладке или исследовании всегда держите эту мысль в глубине души: временные метки и их порядок могут не сказать вам всю правду. В конечном итоге вы не можете знать со 100% уверенностью, что и когда произошло.
person
Basil Bourque
schedule
23.11.2020