原创
SimpleDateFormat的线程安全问题
异常描述
// 如果没有加锁,没有去保证线程安全的话,那这个就是错误的写法,是线程不安全的
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
错误示例:
package com.lzhpo.common.config;
import org.junit.jupiter.api.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* @author Zhaopo Liu
*/
class DateFormatConfigTest {
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* SimpleDateFormat线程不安全,没有保证线程安全的情况下,禁止使用全局SimpleDateFormat
* <pre>
* private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
* </pre>
*/
@Test
void testParse() {
for (int i = 0; i < 20; ++i) {
Thread thread = new Thread(() -> {
try {
// 错误
System.out.println(SIMPLE_DATE_FORMAT.parse("2020-06-01 11:35:00"));
// 正确
// System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2020-06-01 11:35:00"));
} catch (ParseException e) {
e.printStackTrace();
}
});
thread.start();
}
}
}
报错:
异常分析
从代码中可以看到:SimpleDateFormat继承DateFormat类,在SimpleDateFormat转换日期是通过Calendar对象来操作的,DateFormat类中维护一个Calendar对象,Calendar对象会被用来进行日期-时间计算,既被用于format方法也被用于parse方法。
那就追一下calendar
对象:
来到了CalendarBuilder
的establish
方法:
看一下clear
方法,可以发现它并不是线程安全的,如果此时,a线程将calendar
清空了,calendar
就没有新值了,恰好此时b线程刚好进入到parse
方法用到了calendar
对象,那就会产生线程安全问题了!
解决办法
不使用静态变量
SimpleDateFormat
,使用局部变量SimpleDateFormat
,每次都new一个。synchronized
等等...保证线程安全的情况下使用静态变量SimpleDateFormat
。使用
ThreadLocal.withInitial
/** * 创建线程局部变量SimpleDateFormat */ private static final ThreadLocal<DateFormat> SAFE_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); @Test void testSafe() { for (int i = 0; i < 20; ++i) { Thread thread = new Thread(() -> { try { System.out.println(SAFE_FORMAT.get().parse("2020-06-01 11:35:00")); } catch (ParseException e) { e.printStackTrace(); } }); thread.start(); } }
- 本文作者: lzhpo
- 本文链接: http://www.lzhpo.com/article/166
- 版权声明: 本文为本人原创文章,采用 CC BY 3.0 CN协议 ,可自由转载、引用,但需署名作者且注明文章出处。
正文到此结束
- 本文标签: Spring Boot Java Spring
- 版权声明: 本站原创文章,于2020年12月24日由lzhpo发布,转载请注明出处