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();
}
}