java踩过的坑--SimpleDateFormat线程不安全

在一次项目上线的时候,发现老是出现数据丢失问题,通过日志发现SimpleDateFormat是线程不安全的!!!

代码:
private static SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public static Date string2DateTime(String dateStr) {
        Date date = null;
        try {
            if (string != null && !string.trim().equals("")) {
                date = dateTimeFormat.parse(string);
            }
        } catch (Exception e) {
            logger.warn("字符串转日期值失败!" + e.getMessage());
        }
        return date;
    }
报错:
2018-12-04 18:12:27.696 WARN  pool-1-thread-9 128 [DateUtil.java:128] 字符串转日期值失败!For input string: "E111133E2"
2018-12-04 18:12:27.696 WARN  pool-1-thread-10 128 [DateUtil.java:128] 字符串转日期值失败!For input string: "E111133"
2018-12-04 18:12:27.696 WARN  pool-1-thread-2 128 [DateUtil.java:128] 字符串转日期值失败!For input string: "E111133E2.11E2"
2018-12-04 18:12:27.696 WARN  pool-1-thread-8 128 [DateUtil.java:128] 字符串转日期值失败!For input string: "E111133E2.11E22E2"
2018-12-04 18:12:27.696 WARN  pool-1-thread-5 128 [DateUtil.java:128] 字符串转日期值失败!For input string: "E111133E2.11E22"
  • 通过上述可见报错日志可见,发生了类型转换异常,debug发现传入的参数dateStr是正确的时间参数,但是抛出了报错日志中的错误。后来搜索发现是SimpleDateFormat是线程不安全的。
解决方案:
1. 将SimpleDateFormat定义成局部变量。
缺点:每调用一次方法就会创建一个SimpleDateFormat对象,方法结束又要作为垃圾回收。

2.方法加同步锁synchronized,在同一时刻,只有一个线程可以执行类中的某个方法。
缺点:性能较差,每次都要等待锁释放后其他线程才能进入。

3.使用第三方库joda-time,由第三方考虑线程不安全的问题。(可以使用)

4.使用ThreadLocal:每个线程拥有自己的SimpleDateFormat对象。(推荐使用)

你可能感兴趣的:(java踩过的坑--SimpleDateFormat线程不安全)