2016-07-05 39 views
4

我有以下签名一个静态方法:静态方法的并发访问,其被用于计算逾期天

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 

只有是正确的答案。 但是,当我更换日历乔达时间,它返回正确的answer.How我应该改变这种代码,而无需使用乔达时间解锁,并得到正确的答案。

+0

你可以标记方法'synchronized';但你可能不需要 - 在这个方法中是否有任何静态变量? –

+1

'payDayFormat'类型是什么? –

+0

如果你有Java 8,你可以使用Java时间,(这几乎是Joda时间) –

回答

8

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

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

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

所以,你可以:

  • 添加​​方法签名;
  • 添加​​块只是围绕在您使用payDayFormat

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

  • 使payDayFormat a ThreadLocal<SimpleDateFormat>,以便每个线程都有自己的副本。