避坑!SimpleDateFormat不光线程不安全,还有这个隐患()

  本篇文章为你整理了避坑!SimpleDateFormat不光线程不安全,还有这个隐患()的详细内容,包含有 避坑!SimpleDateFormat不光线程不安全,还有这个隐患,希望能帮助你了解 避坑!SimpleDateFormat不光线程不安全,还有这个隐患。

  众所周知,SimpleDateFormat是多线程不安全的

  下面这段代码通过多线程使用同一个SimpleDateFormat对象的parse方法, 多次执行代码来测试,可以看到会出现两种预想不到的现象----- 要么出现不正确的时间解析结果,要么抛出message各异的NumberFormatException异常。 @see 借助SimpleDateFormat来谈谈java里的多线程不安全

  

package jstudy.dateformat;

 

  import java.text.ParseException;

  import java.text.SimpleDateFormat;

  import java.util.concurrent.ExecutorService;

  import java.util.concurrent.Executors;

  public class SimpleDateFormatTest {

   public static void main(String[] args) throws ParseException, InterruptedException {

   ExecutorService threadPool = Executors.newFixedThreadPool(20);

   SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

   String startDate = "2022-01-07 15:40:15";

   for (int i = 0; i i++) {

   threadPool.execute(() - {

   for (int j = 0; j j++) {

   try {

   // new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(startDate); //使用局部变量可以避免出现线程不安全

   System.out.println(datetimeFormat.parse(startDate));

   } catch (ParseException e) {

   e.printStackTrace();

  }

 

  

  SimpleDateFormat不光线程不安全,还有这个隐患

  如下代码运行结果是什么?

  

 @Test

 

   public void test() throws ParseException {

   SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyyMMddHHmmss");//pattern

   System.out.println( simpleDateFormat.parse("2022-09-30 13:53:14"));

   }

 

  

  答案:

  

Wed Dec 08 21:00:13 CST 2021

 

  

  
可见,字符串时间与指定的pattern不匹配,导致出现意外结果。

  而我们这次在现网排查问题时,正好是遇到了这个坑。

  
数据库里的付款记录,竟然存在付款完成时间比记录创建时间还早的付款单,而且还早了多半年。

  我们可以确定的是create_time赋值是没问题的。那看来就是payment_finish_time的赋值有问题。

  赶紧扒代码,在三方付款服务商的service里,发现如下语句:

  

//完成时间

 

  payResultVo.setOrderFinishTime(DateUtils.str2Date(qi.getEndTime(),DateUtils.datetimeFormat));

 

  其中,DateUtils 存在于公司公共技术common包,封装了时间相关处理操作,DateUtils#str2Date 是将特定格式的时间字符串转换成Date对象。DateUtils.datetimeFormat 是 public static final SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

  瞬间想到,必然是SimpleDateFormat线程不安全导致的。为了快速解决问题,修改DateUtils#str2Date 的实现:

  


 1 public static Date str2Date(String str, SimpleDateFormat sdf) {

 

   2 if (null == str "".equals(str)) {

   3 return null;

   5 try {

   6 return sdf.parse(str);

   7 } catch (ParseException e) {

   8 e.printStackTrace();

  10 return null;

  11 }

 

  

  


 1 public static Date str2Date(String str, SimpleDateFormat sdf) {

 

   2 if (null == str "".equals(str)) {

   3 return null;

   5 try {

   6 SimpleDateFormat actualSdf = new SimpleDateFormat(sdf.toPattern());

   7 return actualSdf.parse(str);

   8 } catch (ParseException e) {

   9 e.printStackTrace();

  11 return null;

  12 }

 

  

  
后来竟然发现这个改动没起作用!就是说,依然存在付款完成时间早于创建时间的付款单。这就不科学了~

  排查原因着实费了几番周折。

  再后来,才真相大白。原来,服务商响应报文里的时间格式不是yyyy-MM-dd HH:mm:ss,而是yyyyMMddHHmmss 。由于程序员当时的粗心,直接拷贝别的对接程序里的代码,再加上测试没有覆盖到这个case,导致运行了一个月,才发现这个问题。

  赶紧加上个必要的代码注释,给“伸手党”式的粗心同学提个醒。

  

  
当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge
本文来自,转载请注明原文链接:https:///buguge/p/16744992.html

  以上就是避坑!SimpleDateFormat不光线程不安全,还有这个隐患()的详细内容,想要了解更多 避坑!SimpleDateFormat不光线程不安全,还有这个隐患的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: