DateTimeFormatter 是 java.time 包中用于格式化 / 解析日期时间的核心类,其内部包含复杂的解析规则和时区信息。频繁创建 DateTimeFormatter 实例会导致:
对象创建开销:每次创建都需要解析格式字符串(如yyyy-MM-dd)、初始化解析器链,耗时约数百纳秒(在高并发场景下累积效应显著)。
GC 压力增大:短期大量实例被回收,触发 Minor GC,影响系统响应速度。
注意,DateTimeFormatter 是线程安全的不可变对象(Immutable),其设计初衷就是支持多线程共享。因此,缓存并复用实例不会引发线程安全问题,且能避免重复初始化的开销。
在工具类中定义 static final 常量,全局复用同一 Formatter 实例,例如:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateTimeUtils {
// 全局缓存的Formatter(线程安全,可共享)
public static final DateTimeFormatter STANDARD_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 禁止实例化工具类
private DateTimeUtils() {}
// 格式化方法(复用全局Formatter)
public static String format(LocalDateTime dateTime) {
return dateTime.format(STANDARD_FORMATTER);
}
// 解析方法(复用全局Formatter)
public static LocalDateTime parse(String str) {
return LocalDateTime.parse(str, STANDARD_FORMATTER);
}
}
若系统需要支持多种格式(如同时处理 yyyy-MM-dd 和 yyyyMMdd),可通过 ConcurrentHashMap 缓存 Formatter 实例,避免重复创建:
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DateTimeFormatterCache {
// 线程安全的缓存容器
private static final Map<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>();
// 获取Formatter(存在则复用,不存在则创建并缓存)
public static DateTimeFormatter getFormatter(String pattern) {
// 利用ConcurrentHashMap的computeIfAbsent原子操作,避免并发创建
return FORMATTER_CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
}
// 使用示例
public static void main(String[] args) {
DateTimeFormatter formatter1 = getFormatter("yyyy-MM-dd");
DateTimeFormatter formatter2 = getFormatter("yyyy-MM-dd"); // 复用缓存中的实例
System.out.println(formatter1 == formatter2); // 输出:true(同一实例)
}
}
错误1:在循环中创建 Formatter
// 低效:每次循环创建新实例
for (int i = 0; i < 1000000; i++) {
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}错误2:使用局部变量缓存(无效)
// 无效:方法每次调用仍会创建新实例
public void process() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// ...使用formatter
}