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 }