并发访问用于计算逾期天数的静态方法

时间:2016-07-05 09:46:57

标签: java concurrency calendar

我有一个带有以下签名的静态方法:

private static volatile SimpleDateFormat payDayFormat = new SimpleDateFormat("yyyyMMdd");
public static int overdueDays(String repayDay){
    try {
        Date billDate = payDayFormat.parse(repayDay);
        Calendar startDate = Calendar.getInstance();
        startDate.setTime(billDate);
        Calendar endDate = Calendar.getInstance();
        long end = endDate.getTimeInMillis();
        long start = startDate.getTimeInMillis();
        Long days = TimeUnit.MILLISECONDS.toDays(Math.abs(end - start));
        return days.intValue();
    } catch (ParseException e) {
        logger.error("判断是否逾期解析时间出错");
    }
    return 0;
}

当同一个参数同时对上述方法进行多次调用时,结果不同。

56
56
1279716
56
56
56
5
736387
56
-1226645849
56

只有 56 才是正确答案。 但当我用 Joda-Time 替换日历时,它会返回正确的答案。如何更改此代码而不使用 Joda-Time 锁定解锁并得到正确答案。

1 个答案:

答案 0 :(得分:8)

这是因为共享payDayFormat,这是一个SimpleDateFormat

  

日期格式未同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问格式,则必须在外部进行同步。

它与Jodatime合作的原因是它的日期格式化程序没有共享可变状态,因为它是明智的。

所以,你可以:

  • synchronized添加到方法签名;
  • 在您使用synchronized的位置附近添加payDayFormat块:

    Date billDate;
    synchronized (payDayFormat) {
      billDate = payDayFormat.parse(repayDay);
    }
    
  • 在方法中创建SimpleDateFormat的新实例;

  • payDayFormat设为ThreadLocal<SimpleDateFormat>,以便每个帖子都有自己的副本。