共享SimpleDateFormat的并发问题

1、问题提出

梳理订单逻辑时发现对日期格式进行format的代码有如下写法
在这里插入图片描述

在这里插入图片描述

OneDateUtil中定义了一个全局static的SimpleDateFormat对象。SimpleDateFormat对象不是线程安全的,在多线程环境下容易造成数据转换和处理错误

2、为什么SimpleDateFormat线程不安全

SimpleDateFormat在类的注释中标明了并不适合多线程场景
在这里插入图片描述
深入排查,会发现SimpleDateFormat中的format方法中,会将输入的日期给calendar赋值,由于SimpleDateFormat被定义为static类型的,可以被多个线程访问到。当a线程执行了calendar.setTime(date)后,b线程又执行了calendar.setTime(date),此时a线程未执行结束,a线程中的calendar就会被覆盖
在这里插入图片描述
在这里插入图片描述
SimpleDateFormat的parse方法有同样的问题,多线程下执行cal.clear()会出现线程安全问题
在这里插入图片描述
在这里插入图片描述

3、如何修改

方案1:加锁 synchronized修饰,影响性能,禁止。

方案2:局部变量方式,项目中也存在该使用方式,高并发下会创建大量的SimpleDateFormat类对象,不推荐。
在这里插入图片描述
方案3:java 8 中引入新的日期类 API,这些类是不可变的,且线程安全的,推荐。

private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

public static String formatDate(Date date) {
	LocalDateTime time = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
	return formatter.format(time);
}

DateTimeFormatter的format方式是将入参对象封装在一个新建的DateTimePrintContext对象中,作为入参传给printerParser对象,以局部变量的方式传入到方法中,而不是像SimpleDateFormat那样把日期对象设置到全局变量calendar中进行处理,从而避免了线程安全的问题
在这里插入图片描述

4、风险点

1、前端传的日期非正规日期格式
在这里插入图片描述
2、序列化问题

需要进行序列化的地方,可能存在问题,可以通过加注解解决

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime localDateTime ;



@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate localDate;
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的大李子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值