Created Thread 2, Wed Jan 01 00:00:00 HKT 2200
Created Thread 6, Fri Jan 01 00:00:00 HKT 2016
Created Thread 7, Fri Jan 01 00:00:00 HKT 2016
Created Thread 8, Fri Jan 01 00:00:00 HKT 2016
Created Thread 4, Fri Jan 01 00:00:00 HKT 2016
Created Thread 3, Fri Jan 01 00:00:00 HKT 2016
Created Thread 9, Fri Jan 01 00:00:00 HKT 2016
Created Thread 0, Wed Jan 01 00:00:00 HKT 2200
Created Thread 1, Fri Jan 01 00:00:00 HKT 2016
Created Thread 5, Fri Jan 01 00:00:00 HKT 2016
Created Thread 1, Sat May 26 09:34:08 HKT 164390675
Created Thread 3, Fri Jan 01 00:00:00 HKT 2016
Created Thread 4, Fri Jan 01 00:00:00 HKT 2016
Created Thread 0, Fri Jan 01 00:00:00 HKT 42016
Created Thread 5, Fri Jan 01 00:00:00 HKT 2016
Created Thread 6, Fri Jan 01 00:00:00 HKT 2016
Created Thread 2, Fri Jan 01 00:00:00 HKT 42016
Created Thread 7, Fri Jan 01 00:00:00 HKT 2016
java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1110)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2088)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.examples.tutorials.SimpleDateFormatNotThreadSafe$MyThread.run(SimpleDateFormatNotThreadSafe.java:27)
java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1110)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.examples.tutorials.SimpleDateFormatNotThreadSafe$MyThread.run(SimpleDateFormatNotThreadSafe.java:27)
java.lang.NumberFormatException: For input string: ".11E.111E"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1250)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.examples.tutorials.SimpleDateFormatNotThreadSafe$MyThread.run(SimpleDateFormatNotThreadSafe.java:27)
java.lang.NumberFormatException: For input string: ".11E.111E1"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1250)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.examples.tutorials.SimpleDateFormatNotThreadSafe$MyThread.run(SimpleDateFormatNotThreadSafe.java:27)
Created Thread 1, Fri Jan 01 00:00:00 HKT 2016
Created Thread 6, Fri Jan 01 00:00:00 HKT 2016
Created Thread 3, Fri Jan 01 00:00:00 HKT 2016
Created Thread 5, Fri Jan 01 00:00:00 HKT 2016
Created Thread 4, Fri Jan 01 00:00:00 HKT 2016
Created Thread 7, Fri Jan 01 00:00:00 HKT 2016
Created Thread 8, Fri Jan 01 00:00:00 HKT 2016
Created Thread 9, Fri Jan 01 00:00:00 HKT 2016
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.
如何写出线程安全的date formatter
针对写出线程安全的date formatter,在Java 8之前主要有三种方法:
每个线程使用单独的DateFormat实例
使用synchronized进行同步
使用ThreadLocal
每个线程使用单独的DateFormat实例
在每个线程里,创建一个新的DateFormat实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatThreadSafe {
public Date convertStringToDate(String dateString) throws ParseException {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
return df.parse(dateString);
}
}
这种方法虽然实现起来很简单,但是效率非常的低。
使用synchronized进行同步
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatThreadSafeSynchronized {
private static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd");
public Date convertStringToDate(String dateString) throws ParseException {
Date result;
synchronized(FORMAT) {
result = FORMAT.parse(dateString);
}
return result;
}
}
使用ThreadLocal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class ThreadLocalThreadSafe {
private static final ThreadLocal<DateFormat> FORMAT = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue(){
return new SimpleDateFormat("yyyy-MM-dd");
}
};
public Date convertStringToDate(String dateString) throws ParseException {
return FORMAT.get().parse(dateString);
}
}