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()); // может бросить NPEException 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 для тестируемости
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
long start = System.nanoTime();
// операция
long end = System.nanoTime();
System.out.println((end - start) + " ns");
1234567 ns
3) Привязка активности к именам потоков через ThreadFactory
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
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) Использование текущей зоны в приложении, зависимом от окружения
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()-подобными методами
// Пример безопасной проверки
var ctx = javax.faces.context.FacesContext.getCurrentInstance();
if (ctx != null) {
// работать с ctx
} else {
// альтернативный путь вне контекста запроса
}
нет вывода; демонстрация подхода
7) Комбинация Instant и Clock для имитации временных зон и сдвигов
Clock offsetClock = Clock.offset(Clock.systemUTC(), Duration.ofHours(3));
System.out.println(Instant.now(offsetClock));
2021-04-08T15:34:03.456Z // эквивалент UTC+3 по сдвигу
Каждый из примеров демонстрирует практическое применение «current»-методов для реальных задач: тестирование, измерения, форматирование и безопасное использование контекстов.