尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
【Java踩坑笔记】47_日期时间计算还在用SimpleDateFormat?线程不安全
47 | 日期时间计算还在用 SimpleDateFormat线程不安全摘要SimpleDateFormat不是线程安全的多线程共享一个实例会导致数据错乱甚至抛异常。Java 8 用DateTimeFormatter不可变线程安全。一、问题现象// ❌ 多线程共享 SimpleDateFormat数据错乱privatestaticfinalSimpleDateFormatFMTnewSimpleDateFormat(yyyy-MM-dd);publicstaticvoidmain(String[]args){for(inti0;i10;i){newThread(()-{try{System.out.println(FMT.parse(2024-01-01));}catch(Exceptione){e.printStackTrace();// ❌ 多线程下可能抛异常}}).start();}}现象偶尔出现NumberFormatException或解析出错误日期。二、踩坑现场场景Web 项目里共用 SimpleDateFormat// ❌ 错误定义为静态字段多线程共享ComponentpublicclassDateService{privatestaticfinalSimpleDateFormatFMTnewSimpleDateFormat(yyyy-MM-dd HH:mm:ss);publicStringformat(Datedate){returnFMT.format(date);// ❌ 多线程并发结果错乱}}结果并发请求下格式化结果出现错乱日期。三、原理解析3.1 为什么线程不安全SimpleDateFormat内部用Calendar实例做计算而Calendar是可变对象线程 Afmt.format(date1) → 修改内部 calendar 字段 线程 Bfmt.format(date2) → 同时修改同一个 calendar → 数据竞争结果不可预测3.2 三种错误用法对比用法问题静态字段共用❌ 线程不安全每次创建新实例⚠️ 性能差频繁创建对象加synchronized⚠️ 并发性能差四、正确写法4.1 Java 8用DateTimeFormatter推荐// ✅ 不可变线程安全privatestaticfinalDateTimeFormatterFMTDateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss);publicStringformat(LocalDateTimetime){returntime.format(FMT);// ✅ 线程安全}4.2 Java 7-用ThreadLocal缓存// ✅ 每个线程有自己的 SimpleDateFormat 实例privatestaticfinalThreadLocalSimpleDateFormatFMT_HOLDERThreadLocal.withInitial(()-newSimpleDateFormat(yyyy-MM-dd));publicStringformat(Datedate){returnFMT_HOLDER.get().format(date);}4.3 需要 Date ↔ LocalDateTime 互转// ✅ Java 8 互转DatedatenewDate();LocalDateTimetimedate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();LocalDateTimenowLocalDateTime.now();Datedate2Date.from(now.atZone(ZoneId.systemDefault()).toInstant());五、最佳实践✅ 日期时间处理的 4 条铁律Java 8 全面用java.time包LocalDate、LocalDateTime、DateTimeFormatterSimpleDateFormat不是线程安全的不要定义为静态字段老代码迁移Date→InstantCalendar→LocalDateTime**时区处理用ZoneId不要用TimeZone**java.time包的优势类替换优势LocalDateDate只有日期不可变线程安全LocalDateTimeCalendar日期时间不可变DateTimeFormatterSimpleDateFormat不可变线程安全InstantDate时间戳时区无关六、小结SimpleDateFormat不是线程安全的静态共用会数据错乱Java 8 用DateTimeFormatter不可变线程安全老代码用ThreadLocalSimpleDateFormat缓存每个线程的实例java.time包全面替换Date/Calendar不可变且 API 更友好下一篇预告用 Optional 消灭 NPE但别把它当万能药——Optional的设计目的是减少 NPE但滥用反而让代码更难读。
RELATED

相关推荐

HEAD请求实战指南:从原理到性能优化的深度探索

HEAD请求实战指南:从原理到性能优化的深度探索

1. HEAD请求的本质与核心价值第一次听说HEAD请求时,你可能会有这样的疑问:既然已经有了GET请求,为什么还需要一个不返回响应体的请求方法?这就像去餐厅吃饭时,服务员先给你看菜单(HEAD请求)&…

📅 2026/11/6 9:07:40
python 连接拓竹打印机

python 连接拓竹打印机

目录 怎么查看序列号: 连接代码:conn_tool.py 怎么查看序列号: 机器屏幕中:设置,设备和序列号,序列号,里面有序列号 连接代码: conn_tool.py 可以获取打印进度。 import time import bambulabs_api as blclass BambuPrinter:def __init__(self, ip, access_code, se…

📅 2026/10/25 13:16:31
电子元器件实战检测:从基础工具到进阶技巧

电子元器件实战检测:从基础工具到进阶技巧

1. 电子元器件检测入门:工具准备与基础操作 刚入行那会儿,我最常被问到的就是"这块电路板不工作了,到底哪个元件坏了?"说实话,第一次面对密密麻麻的元器件时,我也是一头雾水。但经过这些年的摸爬…

📅 2026/10/5 21:39:56
MORE NEWS

更多资讯

📰

CNN人脸识别四段流水线:检测对齐、Embedding与阈值标定实战

简介:面向具备深度学习基础、希望用卷积神经网络完成人脸识别实战的开发者与学习者,这份代码包围绕Olivetti人脸数据集给出从模型训练到识别调用的完整实现,可用于课程实验、算法复现和入门项目练习。压缩包共4个文件,以2个Python…

📰

单机模拟横向联邦学习:FedAvg工程实践与调参指南

简介:面向希望理解横向联邦学习完整流程的Python开发者与机器学习初学者,这份项目资料以本地模拟方式复现多客户端独立训练、中央服务器聚合并广播全局模型的协作过程,适合用作课程实验、毕业设计原型或分布式机器学习入门练习。压缩包共25个…

📰

Java Swing 手搓森林冰火人:游戏循环与 AABB 碰撞实战

简介:面向Java初学者、课程设计实践者与游戏开发入门读者的森林冰火人单人版工程,围绕角色行走跳跃、水晶收集、积分累计和倒计时失败等玩法,涉及Swing图形界面、键盘事件监听、游戏循环、重力模拟与碰撞检测等知识点,可用于项目练…

📰

Python股票大数据分析:爬虫、复权清洗与量化回测实战

简介:面向希望将Python用于股票数据采集与量化分析的初学者和进阶者,这份实战资料围绕爬虫抓取、数据清洗、可视化与机器学习预测搭建学习路径,重点解决真实行情数据获取难、预处理流程分散、分析结果难以落地等问题。内容涉及BeautifulSoup、…

📰

股票大数据分析Python实战:从爬虫清洗到因子回测的数据链路

简介:面向具备Python基础、希望切入金融数据场景的学习者与量化分析入门者,这份资料围绕股票大数据采集、清洗、分析与预测展开,覆盖爬虫获取行情、公告与新闻资讯,Pandas处理缺失值和异常值,NumPy/SciPy统计计算&…

📰

GROMACS 分子动力学模拟选型指南:GPU 卸载机制解析与 CPU/GPU 混合工作站配置

摘要:GROMACS 官方手册明确指出其采用混合/异构加速:把最耗时的非键力计算(以及可选的 PME、键合力、约束更新)卸载到 GPU,同时与 CPU 上的其余工作并行。这意味着 MD 工作站不是“GPU 越强越好”,而是要在…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬