SimpleDateFormat线程不安全
2023-09-11 14:22:17 时间
1,问题引发
1 @Test
2 public void testParse() {
3 ExecutorService executorService = Executors.newCachedThreadPool();
4 List<String> dateStrList = Lists.newArrayList(
5 "2018-04-01 10:00:01",
6 "2018-04-02 11:00:02",
7 "2018-04-03 12:00:03",
8 "2018-04-04 13:00:04",
9 "2018-04-05 14:00:05"
10 );
11 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
12 for (String str : dateStrList) {
13 executorService.execute(() -> {
14 try {
15 simpleDateFormat.parse(str);
16 TimeUnit.SECONDS.sleep(1);
17 } catch (Exception e) {
18 e.printStackTrace();
19 }
20 });
21 }
22 }
报错
2,原因
在SimpleDateFormat转换日期是通过Calendar对象来操作的,SimpleDateFormat继承DateFormat类,DateFormat类中维护一个Calendar对象。
通过DateFormat类中的注释可知:此处Calendar实例被用来进行日期-时间计算,既被用于format方法也被用于parse方法!
在parse方法的最后,会调用CalendarBuilder的establish方法,入参就是SimpleDateFormat维护的Calendar实例,在establish方法中会调用calendar的clear方法,如下:
可知SimpleDateFormat维护的用于format和parse方法计算日期-时间的calendar被清空了,如果此时线程A将calendar清空且没有设置新值,线程B也进入parse方法用到了SimpleDateFormat对象中的calendar对象,此时就会产生线程安全问题。
3,解决方法
每一个使用SimpleDateFormat对象进行日期-时间进行format和parse方法的时候就创建一个新的SimpleDateFormat对象,用完就销毁即可!
1 /**
2 * 模拟并发环境下使用SimpleDateFormat的parse方法将字符串转换成Date对象
3 */
4 @Test
5 public void testParseThreadSafe() {
6 ExecutorService executorService = Executors.newCachedThreadPool();
7 List<String> dateStrList = Lists.newArrayList(
8 "2018-04-01 10:00:01",
9 "2018-04-02 11:00:02",
10 "2018-04-03 12:00:03",
11 "2018-04-04 13:00:04",
12 "2018-04-05 14:00:05"
13 );
14 for (String str : dateStrList) {
15 executorService.execute(() -> {
16 try {
17 //创建新的SimpleDateFormat对象用于日期-时间的计算
18 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
19 simpleDateFormat.parse(str);
20 TimeUnit.SECONDS.sleep(1);
21 simpleDateFormat = null; //销毁对象
22 } catch (Exception e) {
23 e.printStackTrace();
24 }
25 });
26 }
27 }
使用SimpleDateFormat对象进行日期-时间计算时,如果SimpleDateFormat是多个线程共享的就会有线程安全问题!应该让每一个线程都有一个独立的SimpleDateFormat对象用于日期-时间的计算!此时就可以使用ThreadLocal将SimpleDateFormat绑定到线程上,是的该线程上的日期-时间计算顺序的使用SimpleDateFormat对象,这样也可以避免线程安全问题。
相关文章
- 并发集合(六)使用线程安全的NavigableMap
- 并发集合(三)使用阻塞线程安全的列表
- 线程安全与共享资源
- 使用线程安全的 MSWeakTimer ,它不会对目标进行retain操作,避免循环引用
- 为什么线程安全的ACE容器不支持[]操作符
- 安全容器的发展与思考
- 132、Android安全机制(2) Android Permission权限控制机制(转载)
- String copy on write 引发的线程不安全
- activemq安全设置 设置admin的用户名和密码
- java多线程(一)——线程安全的单例模式
- 是否只查看安全传送的网页内容? 去掉 IE弹出窗口
- PHP 源码探秘 - 线程安全的实现原理
- Java SimpleDateFormat 线程不安全问题及解决方法
- Qt对象线程安全
- Qt 可重入和线程安全的理解
- Qt进程和线程之三:线程同步、可重入与线程安全
- Spring框架中的单例Bean是线程安全的吗?
- std string与线程安全_这才是现代C++单例模式简单又安全的实现
- Twistlock使Istio的安全层更强大,更易于监控
- 集合和同步(线程安全)
- 100集华为HCIE安全培训视频教材整理 | GRE技术原理
- 100集华为HCIE安全培训视频教材整理 | 虚拟化技术(一)
- Web安全之综合渗透测试
- Android网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合
- 支持DevOps和功能安全/信息安全的静态代码分析器 Klocwork——工具简介|原厂简介|客户列表
- Java开发之高并发必备篇(五)——线程安全操作之synchronized
- 安全测试——AppScan
- 软件测试8款优秀的API安全测试工具,会用3款工作效率能提升50%
- C# 线程安全集合
- C#多线程实践-锁和线程安全
- JAVA中的线程安全与非线程安全
- Servlet — 线程安全问题
- WLAN安全问题详解