先说结论, SimpleDateFormat
是非线程安全的, 即不要在多线程下使用同一份 SimpleDateFormat
对象.
例如在 web 场景下, 不要共享同一个 SimpleDateFormat
静态变量, 高并发下会有问题
下面, 我们进行验证
/**
* SimpleDateFormat 是否线程安全
*/
@Test
public void testSimpleDateFormatThreadSafe() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ExecutorService executorService = Executors.newFixedThreadPool(1000);
CountDownLatch countDownLatch = new CountDownLatch(1000);
String dateStr = "2021-07-05 20:49:45";
for (int i = 0; i < 100000; i++) {
executorService.submit(() -> {
countDownLatch.countDown();
Date date = sdf.parse(dateStr);
System.out.println(date);
return dateStr;
});
}
executorService.shutdown();
ThreadUtils.sleepQuietly(10000);
}
可以看到解析的日期已经出现问题.
事实上, 官方源码也标注了是非同步实例, 推荐在每个线程创建单独实例
解决:
每次实例化新的 SimpleDateFormat
对象即可, 或者使用 ThreadLocal
确保仅在当前线程下, 对应一个 SimpleDateFormat
对象, 不与其他线程共享
总结: SimpleDateFormat
不是线程安全的, 使用时, 务必确保同一份 SimpleDateFormat
对象不与其他线程共享, 否则高并发情况下会有问题