dateformat java 并发_java.text.DateFormat 多线程并发问题

在日常开发中,java.text.DateFormat 应该算是使用频率比较高的一个工具类,经常会使用它 将 Date 对象转换成字符串日期,或者将字符串日期转化成 Date 对象。先来看一段眼熟的代码:

类 DateUtils 的方法 formatForDay() 在多线程的情况下,可能会得不到想要的结果。给一段多线程并发访问 formatForDay() 方法的示例:

示例代码,创建了100个 RunThread 线程,每个线程根据 i 的值创建不同的日期,并将日期格式化成字符串,和原日期进行对比,若不相等,则打印退出。某次执行的结果见下:

从结果可以看出,格式化后的日期和传给 format() 的日期不一致。

原因分析

类 DateFormat 有个 Calendar 成员变量:

调用 format() 方法,会调用实现类 SimpleDateFormat 的  format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) 方法:

每次调用 format() 方法,会将要格式化的日期设置到成员变量 calendar 中,然后再对其进行格式化,此类实现未进行线程同步,是非线程安全的。

当然,调用 parse() 方法,将 字符串转化成日期,也会有同样的非线程安全问题。

解决方案

每次进行格式化日期调用时,均 new 一个 SimpleDateFormat 对象;缺点是在高并发的情况下,就会频繁创建和销毁对旬,造成开销。

使用 synchronized 关键字 或 Lock 给静态方法加上同步;缺点是在高并发的情况下,所有的线程在此处会引起资源的竞争。

使用 ThreadLocal 对象创建静态 DateFormat 。这样在高并必情况下,有多少个线程,就会创建多少个 DateFormat 对象,既不会无限制创建、销毁对象,也不会引起对象的多线程竞争,如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值