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

标签 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 替换 Calendar 时,它返回正确的答案。我应该如何在不使用 Joda-Time 或 < strong>锁定、解锁并得到正确答案。

最佳答案

是因为分享payDayFormat ,这是一个 SimpleDateFormat :

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

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

因此,您可以:

  • 添加synchronized到方法签名;
  • 添加 synchronized在你使用 payDayFormat 的地方挡住:

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

  • 制作payDayFormat一个ThreadLocal<SimpleDateFormat> , 这样每个线程都有自己的副本。

关于java - 并发访问用于计算逾期天数的静态方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38200192/

相关文章:

java - 有时返回 String 有时返回 null 时如何使用 Assert.assertEquals

java - 集合的并发映射 - 空时删除集合

java - 锁定/监控/关键部分扩展?

concurrency - Centos 7 : Running "Grunt Serve" (concurrent) task 上的 Ionic "concurrent:server"错误

java - 记录 native 代码发出的调用

java - 使用 java 套接字在网络上传输视频

JAVA super 马里奥让马里奥掉进缺口

ios - 从日历中检索带有标识符的事件时应用程序崩溃

C初学编程求助日历代码更新

java - 如何从java中的时区偏移量获取时区?