SimpleDateFormat是線程非安全的。那麼在多線程中,就會出現錯誤的結果如下代碼:
public static void main(String[] args){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Callable<Date> callable = new Callable<Date>() {
@Override
public Date call() throws Exception {
//由於線程非安全,所以往pool中同時放入100個任務並開啓10000個線程去執行如下
的代碼就會報錯。100不報錯,就改成1000,1000不報錯就改成10000.你的機子
越牛逼。這個數字就越大。但是肯定會報錯
return sdf.parse("20181012");
};
};
List<Future<Date>> dates = new ArrayList();
ExecutorService pool = Executors.newFixedThreadPool(10);
for(int i=0;i<10000;i++){
LocalDates.add(pool.submit(callable));
}
dates.forEach((Future<Date> dateFuture) -> {
try {
System.out.println(dateFuture.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
pool.shutdown();
}
這個時候我們會想到一個類。可以實現SimpleDateFormat的線程安全。那就是ThreadLocal。怎麼做呢?如下:
把DateFormat對象初始化後放入到ThreadLocal中加鎖。
1:創建DateFormatThreadLocal類
public class DateFormatThreadLocal {
private static final ThreadLocal<DateFormat> threadLocalDate = new ThreadLocal<DateFormat>(){
protected Date initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
}
public static Date convert(String source){
return threadLocalDate.get().parse(source);
}
}
再執行上述代碼就ok了。
java1.8就不用這麼麻煩了。它提供了LocalDate類 和 DateTimeFormat類。具體代碼如下這兩個類似線程安全的
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* : 描述信息
*
* @author liyy
* @LocalDate 2018-10-16 10:20
*/
public class TestJava8 {
public static void main(String[] args){
// SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
//定義格式化的對象
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
Callable<LocalDate> callable = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
//調用LocalDate.parse方法並傳入格式化對象即可
return LocalDate.parse("20181012",dtf);
};
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> LocalDates = new ArrayList();
for(int i=0;i<10000;i++){
LocalDates.add(pool.submit(callable));
}
LocalDates.forEach((Future<LocalDate> LocalDateFuture) -> {
try {
System.out.println(LocalDateFuture.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
pool.shutdown();
}
}