我们运行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
但没有运气!有什么想法吗?
答案 0 :(得分:34)
一个鲜为人知的事实是SimpleDateFormat
不是线程安全!
不是一个错误:javadoc记录了这种行为:
日期格式未同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问格式,则必须在外部进行同步。
每次需要时创建一个实例,或者如果性能是一个真正的问题,您可以尝试使用ThreadLocal
为每个需要一个的线程存储一个实例。
不要感觉不好:我完全倾向于“优化”(重用一个常量实例),令我惊讶的是,每次都必须实例化一个新实例。
答案 1 :(得分:5)
看起来像this bug report。根本原因被诊断为DecimalFormat
根本不是线程安全的。
所以你不应该在不同的线程上使用相同的SimpleDateFormat
实例,因为它,DecimalFormat
仍然不是线程安全的。
您可以使用ThreadLocal
让每个线程都使用自己的实例。
答案 2 :(得分:1)
每次创建实例的简单方法是使用局部/作用域变量而不是全局变量,
private void test {
SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(pattern, Locale.ENGLISH);
// Do somethings
}
答案 3 :(得分:0)
尝试使用Commons Lang 3.x FastDateParser和FastDateFormat。这些类是线程安全的,比SimpleDateFormat更快。它们还支持与SimpleDateFormat相同的格式/解析模式规范。