测试代码如下:
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws ParseException{
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new TestRunnable(), "t-" + i);
t.start();
}
}
static class TestRunnable implements Runnable {
@Override
public void run() {
while(true) {
long dateTime = 0;
String dateStr = "2016-05-09 08:21:02";
try{
Date dt = sdf.parse(dateStr);
dateTime = dt.getTime();
} catch(Exception e){
e.printStackTrace();
}
if(dateTime < 0) {
System.out.println(dateTime);
}
}
}
}
输出结果:
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:453)
at java.lang.Long.parseLong(Long.java:483)
at java.text.DigitList.getLong(DigitList.java:194)
at java.text.DecimalFormat.parse(DecimalFormat.java:1316)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2088)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
-125744830738000
-61916917138000
-61916917138000
at com.tiza.ngp.rp.sanhui.util.Utils$TestRunnable.run(Utils.java:214)
at java.lang.Thread.run(Thread.java:745)
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:453)
结果要么抛异常,要么结果为错误的负值。
public abstract class DateFormat extends Format {
/**
* The {@link Calendar} instance used for calculating the date-time fields
* and the instant of time. This field is used for both formatting and
* parsing.
*
* <p>Subclasses should initialize this field to a {@link Calendar}
* appropriate for the {@link Locale} associated with this
* <code>DateFormat</code>.
* @serial
*/
protected Calendar calendar;
...
}
DateFormat类使用了Calendar对象来维护parse和format过程中的日期时间值,当多线程同时使用同一个DateFormat对象,也就是多线程同时使用同一个Calendar对象来维护parse或format过程的日期时间值,必定会发生错乱。
引用Java api文档:
Synchronization Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.
使用中要么为每个线程创建一个DateFormat实例,要么对其外部加锁。