news 2026/9/10 2:49:13

SimpleDateFormat 为什么线程不安全

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SimpleDateFormat 为什么线程不安全

SimpleDateFormat线程不安全的,主要原因如下:

1.内部状态可变性

// SimpleDateFormat 内部维护了可变状态 private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) { // 会修改内部的 Calendar 对象 calendar.setTime(date); // ... }

2.共享的 Calendar 实例

每个SimpleDateFormat对象内部都持有一个Calendar实例:

public class SimpleDateFormat extends DateFormat { protected Calendar calendar; // 共享的可变状态 public String format(Date date) { // 1. 设置时间到 calendar calendar.setTime(date); // 2. 使用 calendar 进行格式化 return format(calendar); } }

3.并发问题场景

情况1:多线程同时调用 format()

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 线程A sdf.format(dateA); // 设置 calendar 为 dateA // 线程B在此刻插入 sdf.format(dateB); // 设置 calendar 为 dateB // 线程A继续格式化,但calendar已经被线程B修改

情况2:多线程同时调用 parse()

// 线程A sdf.parse("2024-01-01"); // 线程B sdf.parse("2024-02-01"); // 两者可能互相干扰,得到错误结果

4.问题复现代码

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ExecutorService executor = Executors.newFixedThreadPool(10); List<Future<String>> futures = new ArrayList<>(); for (int i = 0; i < 10; i++) { final int index = i; futures.add(executor.submit(() -> { Date date = new Date(System.currentTimeMillis() + index * 1000); return sdf.format(date); // 可能出现:空指针、格式错误、时间错乱 })); }

5.线程安全的替代方案

方案1:使用 ThreadLocal(推荐)

private static final ThreadLocal<SimpleDateFormat> threadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd")); public String formatDate(Date date) { return threadLocal.get().format(date); }

方案2:每次创建新实例

public String formatDate(Date date) { return new SimpleDateFormat("yyyy-MM-dd").format(date); } // 缺点:频繁创建对象,性能较差

方案3:使用 DateTimeFormatter(Java 8+)

// DateTimeFormatter 是线程安全的 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 格式化 String formatted = LocalDateTime.now().format(formatter); // 解析 LocalDateTime parsed = LocalDateTime.parse("2024-01-26 10:30:00", formatter);

方案4:使用 FastDateFormat(Apache Commons Lang)

FastDateFormat formatter = FastDateFormat.getInstance("yyyy-MM-dd"); String formatted = formatter.format(new Date()); // 线程安全

6.为什么 DateTimeFormatter 线程安全?

public final class DateTimeFormatter { // 所有字段都是 final 的 private final CompositePrinter printer; private final CompositeParser parser; private final Locale locale; // 所有方法都是纯函数,不修改内部状态 public String format(TemporalAccessor temporal) { // 不修改任何实例变量 } }

总结

  • 根本原因SimpleDateFormat内部可变状态(Calendar)在多线程下被共享修改

  • 解决方案

    1. 使用ThreadLocal包装(适合传统项目)

    2. 使用 Java 8+ 的DateTimeFormatter(推荐新项目)

    3. 使用同步锁(性能差,不推荐)

在并发环境下,永远不要共享同一个SimpleDateFormat实例

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 1:32:49

MATLAB 探索声发射波形:参数计算与谱绘制

MATLAB计算给定声发射波形的基本参数和特征参数、绘制单边振幅谱 在材料科学和无损检测等领域&#xff0c;声发射技术作为一种重要的监测手段&#xff0c;能够捕捉到材料内部结构变化时产生的弹性波信号&#xff0c;也就是声发射波形。借助 MATLAB 强大的计算和绘图能力&#x…

作者头像 李华
网站建设 2026/9/5 3:03:41

大型流水线贴膜机项目程序:初学者的福音

大型流水线贴膜机完成项目程序&#xff0c;包含PLC程序和触摸屏程序&#xff0c;程序内 包含上下气缸控制&#xff0c;夹紧气缸控制&#xff0c;输送带电机控制&#xff0c;贴膜伺服控制&#xff0c;旋转电机控制等类容&#xff0c;非常适合学习简单控制工艺及运动控制初学者学…

作者头像 李华
网站建设 2026/9/10 0:57:13

电场流线生成技巧

comsol针尖刺穿表皮细胞数值模拟&#xff0c;可以得到组织细胞浓度分布及电磁场分布&#xff0c;最近在搞生物电穿孔的模拟&#xff0c;拿COMSOL折腾了个针尖刺穿表皮细胞的模型。这玩意儿能同时看到细胞被扎穿时的离子浓度变化和电场分布&#xff0c;特别适合研究微针给药时的…

作者头像 李华
网站建设 2026/9/7 3:39:37

产业链影响:上游受益,下游分化,本土配套加速

产业链影响&#xff1a;上游受益&#xff0c;下游分化&#xff0c;本土配套加速 上游&#xff08;芯片配套 / 服务器 / 数据中心&#xff09;&#xff1a;英伟达在华研发、生产、供应链投入&#xff08;如上海张江基地&#xff09;&#xff0c;将带动 PCB、散热、服务器制造、数…

作者头像 李华
网站建设 2026/9/6 1:52:36

吉时利2400 2410 2430精密数字源表

‌吉时利2400是Tektronix&#xff08;原Keithley&#xff09;推出的图形化系列源测量单元&#xff08;SMU&#xff09;‌&#xff0c;集精密电压/电流源与测量功能于一体&#xff0c;配备触摸屏界面&#xff0c;适用于半导体、医疗等领域的精密电子测试。‌‌ 1‌‌ 2 核心功能…

作者头像 李华
网站建设 2026/9/3 17:14:21

极简排班(安卓)手机端免费排班工具,轮班倒班轻松记录

多数排班工具都以电脑端为主&#xff0c;而这款极简排班专为安卓手机打造&#xff0c;用手机随时查看、设置排班更便捷&#xff0c;且目前完全免费&#xff0c;适配日常排班记录、轮班制办公需求 软件下载地址 软件操作极简&#xff0c;上手无门槛&#xff1a;先添加班次&…

作者头像 李华