黑色星期五之夜打败妈咪模组
121.29M · 2025-09-22
SimpleDateFormat 被公认为经典的线程不安全类,主要原因在于其内部实现机制在多线程环境下存在严重的设计缺陷。以下是其线程不安全的核心原因及典型表现:
SimpleDateFormat 继承自 DateFormat,内部维护了一个共享的 Calendar 实例(protected Calendar calendar
)。该实例在日期解析(parse()
)和格式化(format()
)过程中会被反复修改状态。例如:
format()
方法**:会调用 calendar.setTime(date)
修改日历对象的时间字段;parse()
方法**:同样会操作同一个 Calendar 实例来存储解析结果。当多线程并发调用这些方法时,不同线程可能同时修改或读取 Calendar 的状态,导致数据混乱。例如:
ArrayIndexOutOfBoundsException
或 NumberFormatException
。由于 SimpleDateFormat 的解析和格式化操作是非原子性的,多线程共享同一实例时可能出现以下典型问题:
ParseException
或 NumberFormatException
,甚至出现无报错但生成错误结果的“静默失败”。开发者常误以为用 static final
修饰 SimpleDateFormat 可保证线程安全,实则相反:
static
使实例被所有线程共享,而 final
仅保证引用不可变,无法阻止内部状态被并发修改;static final SimpleDateFormat
时,可能输出诸如 2113-08-28 17:05:30
(明显错误的年份)或 00:00:00
(时间被重置)的异常结果。Java 8 引入的 DateTimeFormatter
通过 不可变对象 设计解决了这一问题:
SimpleDateFormat 的线程不安全本质源于其 共享可变状态 的设计,加上开发者对其 static
使用的误解,使其成为 Java 并发编程中的经典陷阱。解决方案包括使用 ThreadLocal 隔离实例、同步锁(性能较差)或直接升级到线程安全的 DateTimeFormatter
(Java 8+推荐)。
121.29M · 2025-09-22
47.33M · 2025-09-22
97.09M · 2025-09-22