当前位置:网站首页>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
边栏推荐
- 2.1、基于并行上下文注意网络的场景文本图像超分辨率
- .NET 6 study notes (4) - Solve the Nullable warning in VS2022
- Reasons for slow startup of IDEA (1)
- 对象模型-虚指针虚表
- .NET Community Toolkit 8.0.0 版本发布
- Insert a number and sort "Suggested Favorites"
- 二分法
- SQL trill interview: send you a universal template, to?(key, each user to log on to the maximum number of consecutive monthly)
- 程序员的专属浪漫——用3D Engine 5分钟实现烟花绽放效果
- 微软 .NET Core 3.1 年底将结束支持,请升级到.NET 6
猜你喜欢
随机推荐
MASA Stack 第三期社区例会
利用C#传输Json数据
聊聊基于docker部署的mysql如何进行数据恢复
A49 - ESP8266建立AP传输XPT2046AD数据WIFI模块
B43 - 基于STM32单片机的自动视力检测仪
B40 - 基于STM32单片机的电热蚊香蓝牙控制系统
How to adjust futures account opening process and handling fee
单片机的优点和单片机开发的流程
微信开发者工具程序开发好后,不报错,但是黑屏「建议收藏」
CryoEM粒子(Particle)类型预测的数据集构建
价值10亿美元 美国向乌克兰提供单次最大规模安全援助
消防安全培训|暑期“消防课堂”,开讲!
Sigrity PowerSI Characteristic Impedance and Coupling Simulation
@AllArgsConstructor and @NoArgsConstructor
dotnet 6 为什么网络请求不跟随系统网络代理变化而动态切换代理
中科院打脸谷歌:普通电脑追上量子优越性,几小时搞定原本要一万年的计算...
Functions and Features of Smart Home Control System
Redis 定长队列的探索和实践
A51 - 基于STM32的DHT11和LCD显示串口通信仿真
ffmpeg通过rtsp获取h264码流









