Current: примеры (JAVA)

Использование методов current в Java
Раздел: Генерация случайных чисел
current: ThreadLocalRandom

Общее описание и назначение

В Java под словом «current» обычно понимаются методы, возвращающие текущее состояние или контекст: текущий поток, текущее время, текущая часовая зона или текущий экземпляр фреймворка. Такие методы не принимают сложных входных данных и служат для получения снимка состояния в момент вызова.

Ниже перечиснены наиболее часто используемые API, содержащие концепт «current», с описанием сигнатур, аргументов и возвращаемых значений.

  • Thread.currentThread()
    Сигнатура: public static Thread currentThread(). Аргументы: отсутствуют. Возвращает: объект Thread, представляющий поток, в котором выполнен вызов. Полезно для получения имени, идентификатора, состояния и локальных переменных потока.
  • System.currentTimeMillis()
    Сигнатура: public static long currentTimeMillis(). Аргументы: отсутствуют. Возвращает: количество миллисекунд с 1970-01-01T00:00:00Z (Unix epoch). Подходит для отметок времени, но не для измерения интервалов точнее.
  • System.nanoTime()
    Сигнатура: public static long nanoTime(). Аргументы: отсутствуют. Возвращает: монотонный счётчик в наносекундах для измерения интервалов. Не связан с календарным временем.
  • java.time.Instant.now()
    Сигнатуры: public static Instant now() и public static Instant now(Clock clock). Аргументы: опционально Clock. Возвращает: Instant - момент на шкале UTC. Позволяет использовать тестовые часы через Clock.
  • java.time.LocalDateTime.now()
    Сигнатуры: public static LocalDateTime now(), public static LocalDateTime now(ZoneId zone), public static LocalDateTime now(Clock clock). Возвращает: локальную дату и время без информации о зоне.
  • java.time.ZonedDateTime.now()
    Сигнатуры: аналогичные LocalDateTime, но возвращает объект с часовым поясом (ZonedDateTime).
  • ZoneId.systemDefault()
    Сигнатура: public static ZoneId systemDefault(). Возвращает: системную часовую зону JVM.
  • Framework-методы типа getCurrentInstance()
    Примеры: FacesContext.getCurrentInstance() в JSF. Сигнатуры и поведение зависят от фреймворка: обычно возвращают текущий контекст или null вне контекста запроса.

Возвращаемые типы различаются: примитивы (long), объекты времени (Instant, LocalDateTime, ZonedDateTime), объекты контекста (Thread, фреймворк-контексты). Большинство «current»-методов не принимают аргументов, но API времени предлагает варианты с Clock или ZoneId для контроля и тестирования.

Короткие примеры

Ниже показаны компактные примеры использования основных «current»-методов. В каждом примере - код и ожидаемый результат.

Thread.currentThread()

public class T1 {
    public static void main(String[] args) {
        Thread t = Thread.currentThread();
        System.out.println(t.getName() + " id=" + t.getId());
    }
}
"main id=1"  // имя и id могут отличаться

System.currentTimeMillis() и преобразование в Date

long ms = System.currentTimeMillis();
System.out.println(ms);
System.out.println(new java.util.Date(ms));
1617890123456
Tue Apr 08 12:34:03 UTC 2021  // пример

Instant.now() и Instant.now(Clock)

System.out.println(java.time.Instant.now());
System.out.println(java.time.Instant.now(java.time.Clock.systemUTC()));
2021-04-08T12:34:03.456Z
2021-04-08T12:34:03.456Z

LocalDateTime и ZonedDateTime с указанием зоны

System.out.println(java.time.LocalDateTime.now());
System.out.println(java.time.ZonedDateTime.now(java.time.ZoneId.of("Europe/Moscow")));
System.out.println(java.time.ZoneId.systemDefault());
2021-04-08T15:34:03.456
2021-04-08T18:34:03.456+03:00[Europe/Moscow]
Europe/Moscow

Пример framework-метода (JSF)

// Внутри запроса JSF
javax.faces.context.FacesContext ctx = javax.faces.context.FacesContext.getCurrentInstance();
System.out.println(ctx != null ? "has context" : "no context");
has context  // либо "no context" при вызове вне жизненного цикла JSF

Похожие механизмы в Java и их особенности

  • System.nanoTime() - предпочтительнее для измерения интервалов времени, так как монотонен и не подвержен сдвигам системных часов.
  • Clock (java.time.Clock) - позволяет инвертировать зависимость от системного времени: полезно для тестирования и подмены источника времени.
  • Instant/LocalDateTime/ZonedDateTime - выбор зависит от потребности: Instant для глобальной временной точки, LocalDateTime для локальных времён, ZonedDateTime если критична часовая зона.
  • Executors и ThreadFactory - при работе с именованием и созданием потоков предпочтительнее централизованно конфигурировать ThreadFactory, а не полагаться на чтение Thread.currentThread() для определения происхождения задачи.

Выбор между этими вариантами определяется задачей: измерение длительности - nanoTime, запись отметки - Instant или currentTimeMillis, тестируемость - использование Clock.

Эквиваленты в других языках

  • JavaScript
    Date.now() и new Date()
    console.log(Date.now());
    console.log(new Date().toISOString());
    1617890123456
    "2021-04-08T12:34:03.456Z"
  • Python
    time.time(), datetime.datetime.now(), threading.current_thread()
    import time, datetime, threading
    print(time.time())
    print(datetime.datetime.now().isoformat())
    print(threading.current_thread().name)
    1617890123.456
    2021-04-08T15:34:03.456789
    MainThread
  • PHP
    time(), microtime(), объект DateTime
    echo time() . "\n";
    echo (new DateTime())->format(DateTime::ATOM) . "\n";
    1617890123
    2021-04-08T15:34:03+03:00
  • C#
    DateTime.Now, DateTime.UtcNow, Thread.CurrentThread
    Console.WriteLine(DateTime.UtcNow);
    Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
    04/08/2021 12:34:03
    1
  • Go
    time.Now()
    fmt.Println(time.Now())
    2021-04-08 15:34:03.456 +0300 MSK
  • Lua
    os.time(), os.date()
    print(os.time())
    print(os.date("!%Y-%m-%dT%H:%M:%SZ"))
    1617890123
    2021-04-08T12:34:03Z
  • Kotlin
    Использует те же API, что и Java: Instant.now(), LocalDateTime.now(), Thread.currentThread().
    println(java.time.Instant.now())
    println(Thread.currentThread().name)
    2021-04-08T12:34:03.456Z
    main
  • SQL
    STANDARD: CURRENT_TIMESTAMP, диалекты: NOW() (Postgres, MySQL)
    SELECT CURRENT_TIMESTAMP;
    -- или
    SELECT NOW();
    2021-04-08 12:34:03.456+00

Отличия от Java: в некоторых языках доступ к часовому поясу или тестовой подмене времени реализован иначе (например, в Java явный Clock), в других языках время возвращается в системной зоне по умолчанию.

Типичные ошибки и примеры

  • Использование System.currentTimeMillis() для измерения интервалов
    Проблема: системное время может измениться (например, NTP), поэтому результаты будут неточны.
    long t1 = System.currentTimeMillis();
    // ...
    long t2 = System.currentTimeMillis();
    System.out.println(t2 - t1);
    Может дать неверный результат при переключении системного времени.
  • NullPointer при использовании framework.getCurrentInstance()
    Проблема: вызов вне ожидаемого контекста (например, вне запроса) возвращает null.
    javax.faces.context.FacesContext ctx = javax.faces.context.FacesContext.getCurrentInstance();
    System.out.println(ctx.getExternalContext()); // может бросить NPE
    Exception in thread "main" java.lang.NullPointerException
  • Неправильное предположение о потокобезопасности
    Thread.currentThread() возвращает объект, принадлежащий текущему потоку; операции с общими ресурсами по-прежнему требуют синхронизации.
    Thread t = Thread.currentThread();
    // далее изменение общих структур без синхронизации
    
    Гонки данных, непредсказуемое поведение
  • Передача null в Instant.now(Clock)
    Если передать null, будет выброшено исключение.
    Instant i = Instant.now(null);
    Exception in thread "main" java.lang.NullPointerException

Изменения и эволюция API

Ключевое изменение, влияющее на получение текущего времени, произошло в Java 8: введена java.time-библиотека (JSR-310) с Instant, LocalDateTime, ZonedDateTime и Clock, что дало более явный и тестируемый подход по сравнению со System.currentTimeMillis() и java.util.Date. Начиная с Java 8, рекомендуется использовать API java.time для новых разработок.

Изменений в поведении Thread.currentThread() и System.currentTimeMillis() в новых версиях не было. Появление виртуальных потоков в более поздних релизах (Project Loom) не изменило семантику Thread.currentThread(), но сценарии с большим количеством легковесных потоков стали более распространёнными.

Расширенные и редко встречающиеся примеры

1) Использование Clock для тестируемости

Пример java
import java.time.*;

Clock fixed = Clock.fixed(Instant.parse("2021-01-01T00:00:00Z"), ZoneOffset.UTC);
Instant now = Instant.now(fixed);
System.out.println(now);
// Замена в коде: SomeService(clock) -> в тесте передать fixed
2021-01-01T00:00:00Z

2) Измерение длительности с nanoTime

Пример java
long start = System.nanoTime();
// операция
long end = System.nanoTime();
System.out.println((end - start) + " ns");
1234567 ns

3) Привязка активности к именам потоков через ThreadFactory

Пример java
import java.util.concurrent.*;

ThreadFactory tf = new ThreadFactory() {
    private final AtomicInteger idx = new AtomicInteger(0);
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, "worker-" + idx.getAndIncrement());
        return t;
    }
};
ExecutorService es = Executors.newFixedThreadPool(2, tf);
es.submit(() -> System.out.println(Thread.currentThread().getName()));
es.shutdown();
worker-0

4) Конвертация epoch millis в ZonedDateTime

Пример java
long ms = 1617890123456L;
ZonedDateTime zdt = Instant.ofEpochMilli(ms).atZone(ZoneId.of("Europe/Moscow"));
System.out.println(zdt);
2021-04-08T18:34:03.456+03:00[Europe/Moscow]

5) Использование текущей зоны в приложении, зависимом от окружения

Пример java
ZoneId sys = ZoneId.systemDefault();
// Логика, адаптирующая форматирование дат под системную зону
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(sys);
System.out.println(f.format(Instant.now()));
2021-04-08 18:34

6) Безопасная работа с getCurrentInstance()-подобными методами

Пример java
// Пример безопасной проверки
var ctx = javax.faces.context.FacesContext.getCurrentInstance();
if (ctx != null) {
    // работать с ctx
} else {
    // альтернативный путь вне контекста запроса
}
нет вывода; демонстрация подхода

7) Комбинация Instant и Clock для имитации временных зон и сдвигов

Пример java
Clock offsetClock = Clock.offset(Clock.systemUTC(), Duration.ofHours(3));
System.out.println(Instant.now(offsetClock));
2021-04-08T15:34:03.456Z  // эквивалент UTC+3 по сдвигу

Каждый из примеров демонстрирует практическое применение «current»-методов для реальных задач: тестирование, измерения, форматирование и безопасное использование контекстов.

джава current function comments

En
Current Returns the current thread's ThreadLocalRandom