`

SimpleDateFormat是线程不安全的

阅读更多

概述

最近在搞大数据实时计算,期间在解析时经常会用到 SimpleDateFormat对时间进行格式化。通过观察每天的日志经常会发现下列异常:

java.lang.NumberFormatException: For input string: ""
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
        at java.lang.Long.parseLong(Long.java:431)
        at java.lang.Long.parseLong(Long.java:468)
        at java.text.DigitList.getLong(DigitList.java:177)
        at java.text.DecimalFormat.parse(DecimalFormat.java:1297)
        at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)
        at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1311)
        at java.text.DateFormat.parse(DateFormat.java:335)
        at com.xxxxxxx.core.common.util.DateUtil.parseTimestamp(DateUtil.java:95)
        at com.xxxxxxx.core.common.util.DateUtil.parse(DateUtil.java:84)
        at com.xxxxxxx.hbase.generator.LogRowKeyGenerator.generate(LogRowKeyGenerator.java:21)
        ... 22 more

 

 原因

通过查找资料发现SimpleDateFormat是继承自DateFormat类,该类中直接使用了Calendar成员变量,该变量在多线程中共享,是线程不安全的,关于线程安全可以参考这里

protected Calendar calendar;

而我们实际中经常在常量类中定义一个如下的对象:

public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

 在多线程中使用DATE_FORMAT.parse(str)、DATE_FORMAT.format(str)就会遇到上述异常问题。

 究其原因,可以看下SimpleDateFormat源码:

public Date parse(String text, ParsePosition pos)
    {
    
        checkNegativeNumberExpression();
    
        int start = pos.index;
        int oldStart = start;
        int textLength = text.length();
        ........//省略
        //establish方法中会调用 calendar.clear(); 
        parsedDate = calb.establish(calendar).getTime();
        ........//省略

        //采用text 重新给calendar赋值
        start = subParse(text, start, tag, count, obeyCount,
				 ambiguousYear, pos, useFollowingMinusSignAsDelimiter);
        
        ........//省略
        Date parsedDate = calendar.getTime();
        return parsedDate 
    }

 在多线程高并发情况下,A线程执行完成calendar.clear(),但还没有执行getTime(), B线程又执行calendar.clear()方法,当A线程执行getTime()就会报上述异常java.lang.NumberFormatException: For input string: ""。

 

报空指针只是其中一种情况,还会有些未知的错误,就是两个线程中的日期串改。

 

解决办法

我的解决办法就是每次都new SimpleDateFormat()

在工具类中提供一个静态方法每次都new SimpleDateFormat():

public static DateFormat getSimpleDF(){
      return new SimpleDateFormat("yyyy-MM-dd");
}

也可以用ThreadLocal来解决在同一个线程中对 DateFormat进行复用,关于ThreadLocal可以参考这里

分享到:
评论

相关推荐

    simpleDateFormat是线程不安全的

    在Java编程语言中,`SimpleDateFormat`类是一个广泛使用的日期时间格式化工具,但它的线程安全性是一个常常被开发者忽视的问题。标题指出的"simpleDateFormat是线程不安全的",意味着在多线程环境下,如果多个线程...

    高并发之-SimpleDateFormat类的线程安全问题和解决方案.docx

    SimpleDateFormat类的线程安全问题和解决方案 SimpleDateFormat类的线程安全问题 SimpleDateFormat类是Java提供的日期时间转化类,用于将日期和时间类型的数据进行解析和格式化。在Java开发中,SimpleDateFormat类...

    ThreadLocal:如何优雅的解决SimpleDateFormat多线程安全问题

    目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现...事项使用ThreadLocal解决SimpleDateFormat线程安全问题总结...

    由浅入深解析 SimpleDateFormat

    SimpleDateFormat 详解 SimpleDateFormat 是 Java 语言中...然而,在使用时需要注意线程安全和资源消耗问题。通过合理地使用 SimpleDateFormat,我们可以实现日期和时间的高效格式化和解析,提高程序的性能和可读性。

    详解SimpleDateFormat的线程安全问题与解决方案

    在Java编程中,`SimpleDateFormat`是一个常用的日期时间格式化工具类,但它的设计并不是线程安全的。本文将深入探讨`SimpleDateFormat`的线程安全问题及其解决方案。 ### 1. 线程安全问题的原因 `SimpleDateFormat...

    SimpleDateFormat线程不安全的5种解决方案.md

    SimpleDateFormat线程不安全的5种解决方案.md

    SimpleDateFormat线程不安全的5种解决方案.docx

    JDK 8 引入了新的日期时间 API,其中的 DateTimeFormatter 是线程安全的,可以替代 SimpleDateFormat。以下是使用 DateTimeFormatter 的示例: ```java import java.time.LocalDateTime; import java.time.format....

    深入理解Java:SimpleDateFormat安全的时间格式化

    但是,如果使用不小心会导致非常微妙和难以调试的问题,因为DateFormat和SimpleDateFormat类不是线程安全的。在多线程环境下调用format()和parse()方法应该使用同步代码来避免问题。 知识点1: SimpleDateFormat的非...

    关于SimpleDateFormat的非线程安全问题及其解决方案.docx

    3. **使用不可变的日期时间API**:从Java 8开始,提供了新的日期时间API(如`java.time`包下的类),这些API设计为线程安全的,可以替代`SimpleDateFormat`。 ```java import java.time.LocalDate; import java....

    阿里巴巴Java编码规范答案.docx

    一般不要定义 SimpleDateFormat 的 static 变量,如果定义为 static,必须保证线程安全(C)。推荐使用 Apache 封装好的 DateUtils 和 DateFormatUtils 工具类,来处理时间日期转换问题(D)。 7. 格式规约 在格式...

    Java多线程环境下SimpleDateFormat类安全转换

    SimpleDateFormat类是Java中常用的日期格式化类,但是它并不是线程安全的。在多线程环境下,如果多个线程同时使用同一个SimpleDateFormat对象,可能会出现日期格式化错误的问题。 2. 使用ThreadLocal解决线程安全...

    Java SimpleDateFormat线程安全问题原理详解

    Java SimpleDateFormat线程安全问题原理详解 Java SimpleDateFormat线程安全问题是Java开发中一个常见的问题。SimpleDateFormat是Java中一个常用的日期时间格式化类,但是它却存在线程安全问题。在多线程环境下,...

    Java理论与实践:描绘线程安全性

    这类类在设计时就没有考虑线程安全,例如`SimpleDateFormat`,在1.4 JDK之前的版本中并未明确指出其线程不安全,导致许多开发者在并发场景中误用,引发错误。 在文档中清晰地记录类的线程安全性是至关重要的。如...

    Java多线程编程的线程安全性.docx

    Java标准库中有一些类,如ArrayList、HashMap和SimpleDateFormat,并未设计为线程安全,因此在多线程环境下直接使用可能导致数据不一致或其他问题。开发者应当了解每个类的线程安全特性,以便做出正确的选择和适当地...

    java SimpleDateFormat &Calendar

    需要注意的是,由于`SimpleDateFormat`不是线程安全的,所以在多线程环境中,建议为每个线程创建单独的实例。 `Calendar`类则是Java中更底层的日期和时间工具,它提供了一套完整的API来操作日期和时间,包括添加、...

    有关SimpleDateFormat的常用方法说明

    - `SimpleDateFormat`是线程不安全的,如果在多线程环境中使用,需要考虑同步问题。 - 日期和时间的格式化字符串要与实际情况对应,避免出现理解错误。 以上就是关于`SimpleDateFormat`的一些常见用法和注意事项,...

    Java线程安全的计数器简单实现代码示例

    Java线程安全的计数器简单实现代码示例 Java线程安全的计数器简单实现代码示例是一种在Java中实现线程安全的计数器的方法,该方法使用AtomicInteger和volatile关键字来保证计数器的线程安全性。该计数器可以每天从1...

    DateFormat多线程问题

    Java 8 引入了`java.time.format.DateTimeFormatter`,这个类是线程安全的,可以作为`SimpleDateFormat`的一个更优选择。它提供了与`SimpleDateFormat`类似的功能,但避免了线程安全问题。 5. **池化`DateFormat`...

    Java 实例 - 格式化时间SimpleDateFormat使用源代码-详细教程.zip

    `SimpleDateFormat`不是线程安全的,所以在多线程环境中,要么为每个线程创建单独的实例,要么在每次使用后进行同步。 8. **替代方案**: Java 8引入了`java.time`包,其中的`DateTimeFormatter`类提供了更现代且...

Global site tag (gtag.js) - Google Analytics