Рубрики
Без рубрики

Измерьте прошедшее время в Java

Изучите различные способы измерения прошедшего времени в Java

Автор оригинала: baeldung.

1. Обзор

В этой статье мы рассмотрим, как измерить прошедшее время в Java. Хотя это может показаться простым, есть несколько подводных камней, о которых мы должны знать.

Мы рассмотрим стандартные классы Java и внешние пакеты, которые предоставляют функциональные возможности для измерения прошедшего времени.

2. Простые Измерения

2.1. currentTimeMillis()

Когда мы сталкиваемся с требованием измерить прошедшее время в Java, мы можем попытаться сделать это следующим образом:

long start = System.currentTimeMillis();
// ...
long finish = System.currentTimeMillis();
long timeElapsed = finish - start;

Если мы посмотрим на код, это имеет смысл. Мы получаем метку времени в начале и получаем другую метку времени, когда код завершен. Прошедшее время-это разница между этими двумя значениями.

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

2.2. наноТайм()

Другой метод в java.lang.System класс-это nanoTime() . Если мы посмотрим на документацию Java , мы найдем следующее утверждение:

“Этот метод может использоваться только для измерения прошедшего времени и не связан с каким-либо другим понятием системного или настенного времени.”

Давайте воспользуемся этим:

long start = System.nanoTime();
// ...
long finish = System.nanoTime();
long timeElapsed = finish - start;

Код в основном такой же, как и раньше. Единственное различие заключается в методе, используемом для получения временных меток – nanoTime() вместо currentTimeMillis() .

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

Например, для преобразования в миллисекунды мы должны разделить результат в наносекундах на 1.000.000.

Еще одна ловушка с nanoTime() заключается в том, что хотя он обеспечивает точность в наносекундах, он не гарантирует разрешение в наносекундах (т. Е. Как часто обновляется значение).

Однако это гарантирует, что разрешение будет по крайней мере таким же хорошим, как у currentTimeMillis() .

3. Java 8

Если мы используем Java 8 – мы можем попробовать новый java.time.Мгновенный и java.time.Продолжительность занятия. Оба являются неизменяемыми, потокобезопасными и используют свою собственную временную шкалу, временную шкалу Java, как и все классы в новом java.time API.

3.1. Шкала времени Java

Традиционный способ измерения времени состоит в том, чтобы разделить день на 24 часа 60 минут 60 секунд, что дает 86.400 секунд в день. Однако солнечные дни не всегда одинаково длинны.

Шкала времени UTC фактически позволяет дню иметь 86,399 или 86,401 секунды СИ. Секунда СИ является научной “Стандартной международной секундой” и определяется периодами излучения атома цезия 133). Это необходимо для того, чтобы день был выровнен по Солнцу.

Шкала времени Java делит каждый календарный день ровно на 86.400 единиц, известных как секунды . Нет никаких високосных секунд.

3.2. Мгновенный класс

Класс Instant представляет момент на временной шкале. По сути, это числовая временная метка, начиная со стандартной эпохи Java 1970-01-01T00:00:00Z .

Чтобы получить текущую метку времени, мы можем использовать метод Instant.non() static. Этот метод позволяет передавать необязательный параметр Clock . Если этот параметр опущен, он использует системные часы в часовом поясе по умолчанию.

Мы можем хранить время начала и окончания в двух переменных, как и в предыдущих примерах. Далее мы можем рассчитать время, прошедшее между обоими моментами.

Мы можем дополнительно использовать класс Duration и его метод between() для получения длительности между двумя объектами Instant . Наконец, нам нужно преобразовать Длительность в миллисекунды:

Instant start = Instant.now();
// CODE HERE        
Instant finish = Instant.now();
long timeElapsed = Duration.between(start, finish).toMillis();

4. Секундомер

Переходя к библиотекам, Apache Commons Lang предоставляет класс StopWatch , который можно использовать для измерения прошедшего времени.

4.1. Зависимость Maven

Мы можем получить последнюю версию, обновив pom.xml:


    org.apache.commons
    commons-lang3
    3.11

Последнюю версию зависимости можно проверить здесь .

4.2. Измерение Прошедшего Времени С Помощью Секундомера

Прежде всего, нам нужно получить экземпляр класса, а затем мы можем просто измерить прошедшее время:

StopWatch watch = new StopWatch();
watch.start();

Как только у нас будут запущены часы, мы сможем выполнить код, который хотим проверить, а затем в конце мы просто вызовем метод stop () . Наконец, чтобы получить фактический результат, мы вызываем getTime() :

watch.stop();
System.out.println("Time Elapsed: " + watch.getTime()); // Prints: Time Elapsed: 2501

Секундомер имеет несколько дополнительных вспомогательных методов, которые мы можем использовать для приостановки или возобновления наших измерений. Это может быть полезно, если нам нужно сделать наш тест более сложным.

Наконец, давайте отметим, что класс не является потокобезопасным.

5. Заключение

В Java существует множество способов измерения времени. Мы рассмотрели очень “традиционный” (и неточный) способ, используя currentTimeMillis() . Кроме того, мы проверили Секундомер Apache Common и посмотрели на новые классы, доступные в Java 8.

В целом, для простых и правильных измерений прошедшего времени достаточно метода nanoTime () . Он также короче для ввода, чем currentTimeMillis() .

Однако давайте отметим, что для правильного бенчмаркинга вместо измерения времени вручную мы можем использовать фреймворк, подобный Java Microbenchmark Harness (JMH). Эта тема выходит за рамки данной статьи, но мы рассмотрели ее здесь .

Наконец, как всегда, код, используемый во время обсуждения, можно найти на GitHub .