18

我们运行 Java 1.4。

我们有这个方法:

static SimpleDateFormat xmlFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

public static Date fromXml(String xmlDateTime) {
    ParsePosition pp = new ParsePosition(0);
    return xmlFormatter.parse(xmlDateTime, pp);
}

比如哪里xmlDateTime = 2013-08-22T16:03:00。这一直在工作,但突然停止了!

我们现在得到这个异常:

java.lang.ArrayIndexOutOfBoundsException: -1
at java.text.DigitList.fitsIntoLong(DigitList.java:170)
at java.text.DecimalFormat.parse(DecimalFormat.java:1064)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1381)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1159) 

我试图通过使用不同的日期格式在单元测试中重现这一点,即:

2013-08-22T16:03:00
2013-08-22 16:03:00

但没有运气!有任何想法吗?

4

4 回答 4

44

这是一个鲜为人知的事实,SimpleDateFormat不是线程安全的!

不是错误:javadoc记录了这种行为:

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

每次需要时创建一个实例,或者如果性能是一个真正的问题,您可以尝试使用ThreadLocal为每个需要的线程存储一个实例。


不要难过:我完全喜欢这种“优化”(重用单个常量实例),令我惊讶的是,每次都必须实例化一个新实例。

于 2013-08-22T14:31:56.927 回答
5

看起来像这个错误报告。根本原因被诊断为DecimalFormat根本不是线程安全的。

所以你不应该SimpleDateFormat在不同的线程上使用相同的实例,因为它DecimalFormat仍然不是线程安全的。

您可以使用ThreadLocal让每个线程使用自己的实例。

于 2013-08-22T14:30:31.803 回答
1

尝试使用 Commons Lang 3.x FastDateParser 和 FastDateFormat。这些类是线程安全的并且比 SimpleDateFormat 更快。它们还支持与 SimpleDateFormat 相同的格式/解析模式规范。

于 2014-03-19T18:34:48.163 回答
1

每次创建实例的简单方法,一个局部/范围变量而不是全局变量,它对我有用

private void test {
    SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(pattern, Locale.ENGLISH);
    // Do somethings
}
于 2018-10-17T08:05:36.807 回答