2016-12-07 50 views
1

我正在处理的应用程序必须解析大量日期才能执行一些计算。这些数据将从本地SQLite数据库中提取出来,并在转换为Java对象时进行解析。这在整个应用程序中运行良好,但在一种情况下导致了一些非常不寻常的行为。即使它们有效,Java也会错误地解析某些日期

正在加载的屏幕会检索相当大量的数据(此时正在测试大约3k条记录),并且在解析日期的过程中,其中一些数据被错误地解析,即使日期字符串本身是完全有效的。

解析代码看起来像这样

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

try { 
    String dateString = cursor.getString(idx); 
    Date d = df.parse(dateString); 
    System.out.println("Parsed " + dateString + " into " + d); 
} catch (ParseException ex) { 
    ex.printStackTrace(); 
} 

这适用于大多数的日期,但如果这个失败的几个例子是

Parsed 2016-11-30T10:32:29Z into Wed Nov 30 10:32:28 GMT+00:00 2016 
Parsed 2016-11-30T10:48:15Z into Thu Jan 01 01:00:14 GMT+00:00 1970 
Parsed 2016-11-30T10:32:30Z into Wed Nov 30 10:32:29 GMT+00:00 2016 
Parsed 2016-11-30T10:48:16Z into Fri Jan 01 00:48:15 GMT+00:00 2016 
Parsed 2016-11-30T10:32:31Z into Wed Nov 30 10:32:30 GMT+00:00 2016 
Parsed 2016-11-30T10:48:17Z into Fri Jan 01 00:48:16 GMT+00:00 2016 
Parsed 2016-11-30T10:32:32Z into Wed Nov 30 10:32:31 GMT+00:00 2016 
Parsed 2016-11-30T10:32:33Z into Thu Jan 01 01:00:32 GMT+00:00 1970 
Parsed 2016-11-30T10:48:18Z into Wed Nov 30 10:48:17 GMT+00:00 2016 

正如你所看到的,也有一些的日期已被完全解析完全不正确,我很难理解为什么。

我唯一能想到的就是线程化。我有两个后台线程都将同时调用相同的代码,但我不明白他们为什么应该互相干扰。

有没有人有任何线索这里发生了什么,因为我完全失去了这一点?

+3

是您的'df'两个线程之间共享?这将解释它,因为'DateFormat'不是线程安全的。 –

+1

哇。没有意识到像日期格式化器/解析器的东西不会是线程安全的。好吧,重构的时间 – PaReeOhNos

+0

@JonSkeet使用包装日期格式化程序的ThreadLocal变量对它进行了排序。看来现在按预期工作。 – PaReeOhNos

回答

-1

你应该使用semaphore控制线程访问

Semaphore

+1

不,最好在每个线程中简单地创建一个新的SimpleDateFormat。这两个线程在逻辑上不会处理共享的可变数据 - 这只是SimpleDateFormat的线程不安全性质,它会导致问题。线程之间不需要协调。 –