当前位置:网站首页>SimpleDateFormat线程安全问题和解决方案
SimpleDateFormat线程安全问题和解决方案
2022-08-09 16:17:00 【泡^泡】
为什么线程不安全
在多线程环境下,当多个线程同时使用相同的SimpleDateFormat对象(如static修饰)的话,如调用format方法时,多个线程会同时调用calender.setTime方法,导致time被别的线程修改,因此线程是不安全的。
public StringBuffer format(Date date, StringBuffer toAppendTo,FieldPosition pos){
pos.beginIndex = pos.endIndex = 0;
return format(date,toAppendTo,pos.getFieldDelegate());
}
// Called from Format after creating a FieldDelegate
private StringBuffer format(Date date,StringBuffer toAppendTo,FieldDelegate delegate) {
// Convert input date to time field list
calendar.setTime(date);
boolean useDateFormatSymbols = useDateFormatSymbols();
for (int i = 0; i < compiledPattern.length;) {
int tag = compiledPattern[i] >>> 8;
int count = compiledPattern[i++] & 0xff;
if (count == 255) {
count = compiledPattern[i++] << 16;
count |= compiledPattern[i++];
}
switch (tag) {
case TAG_QUOTE_ASCII_CHAR:
toAppendTo.append((char)count);
break;
case TAG_QUOTE_CHARS:
toAppendTo.append(compiledPattern, i, count);
i += count;
break;
default:
subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
break;
}
}
return toAppendTo;
}
protected Calendar calendar;
可以看到,多个线程之间共享变量calendar,并修改calendar。因此在多线程环境下,当多个线程同时使用相同的SimpleDateFormat对象(如static修饰)的话,如调用format方法时,多个线程会同时调用calender.setTime方法,导致time被别的线程修改,因此线程是不安全的。
此外,parse方法也是线程不安全的,parse方法实际调用的是CalenderBuilder的establish来进行解析,其方法中主要步骤不是原子操作。
解决方案
- 使用ThreadLocal,每个线程都拥有自己的SimpleDateFormat对象副本
- 加一把线程同步锁:synchronized(lock)
- 将SimpleDateFormat定义成局部变量
- 使用DateTimeFormatter代替SimpleDateFormat
,DateTimeFormatter是线程安全的,默认提供了很多格式化方法,也可以通过ofPattern方法创建自定义格式化方法。
package com;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SimpleDateFormatTest {
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal();
private static DateFormat getDateFormat(){
//从当前线程的范围内获得一个DateFormat
DateFormat dateFormat = threadLocal.get();
if(dateFormat == null){
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//Thread.currentThread范围内设置一个SimpleDateFormat
threadLocal.set(dateFormat);
}
return dateFormat;
}
public static Date parse(String strDate) throws ParseException {
return getDateFormat().parse(strDate);
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 20;i++){
executorService.execute(()->{
try {
System.out.println(parse("2022-07-09 10:00:00"));
} catch (ParseException e) {
e.printStackTrace();
}
});
}
}
}
格式化日期示例:
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime); // 2019-11-20T15:04:29.017
DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
String strDate=localDateTime.format(dtf);
System.out.println(strDate); // 2019/23/20 15:23:46
解析日期:
DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime localDateTime=LocalDateTime.parse("2019/11/20 15:23:46",dtf);
System.out.println(localDateTime); // 2019-11-20T15:23:46
边栏推荐
猜你喜欢

MASA Stack 第三期社区例会

MySQL的索引你了解吗

聊聊基于docker部署的mysql如何进行数据恢复

MySQL 5.5 series installation steps tutorial (graphical version)

程序员的专属浪漫——用3D Engine 5分钟实现烟花绽放效果

HR to get the entry date RP_GET_HIRE_DATE

称重模块的分类及特点

What is hardware integrated development?What are the cores of hardware integrated development?

.NET Community Toolkit 8.0.0 版本发布

2.1、基于并行上下文注意网络的场景文本图像超分辨率
随机推荐
微软 .NET Core 3.1 年底将结束支持,请升级到.NET 6
【时序数据库InfluxDB】Windows环境下配置InfluxDB+数据可视化,以及使用 C#进行简单操作的代码实例...
期货开户应该了解的行内知识
MySQL的索引你了解吗
硬件开发的发展前景
OpenCV image transformation - histogram equalization
Fees and inquiry methods of futures account opening exchanges
OpenCV 图像变换之 —— 直方图均衡化
Now, how to choose a stage rental LED display?
The Chinese Academy of Sciences slaps Google in the face: ordinary computers catch up with quantum superiority, and can solve calculations that would have taken 10,000 years in a few hours...
MySQL 5.5 series installation steps tutorial (graphical version)
微信开发者工具程序开发好后,不报错,但是黑屏「建议收藏」
PADS generates bitmap
央企施工企业数字化转型的灵魂是什么
uniapp电影购票选座系统源码
《ABP Framework 极速开发》 - 教程首发
What you should know about futures account opening
How to adjust futures account opening process and handling fee
B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶
为了高性能、超大规模的模型训练,这个组合“出道”了