### SimpleDateFormat有多线程问题
日期转换的SimpleDateFormat在多线程环境下有隐患,在java8下我们尝试如何去优化这个问题。测试SimpleDateFormat的多线程问题,多次执行如下程序:
```java
@Test
public void test () throws ExecutionException, InterruptedException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Callable task = new Callable() {
@Override
public Date call() throws Exception {
return sdf.parse("20200909");
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List> results = new ArrayList<>();
for (int i = 0; i < 20; i++) {
results.add(pool.submit(task));
}
for (Future future : results) {
System.out.println(future.get());
}
pool.shutdown();
}
```
多次执行后,必然会报错如下,这个就是SimpleDateFormat的多线程问题:

### ThreadLocal解决多线程安全问题
如果每个线程一个SimpleDateFormat对象,那么可以避免SimpleDateFormat的多线程问题。
新建DateFormatThreadLocal类:
```java
package com.iee.date;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormatThreadLocal {
private static final ThreadLocal df = new ThreadLocal(){
protected DateFormat initialValue(){
return new SimpleDateFormat("yyyyMMdd");
}
};
public static final Date convert(String source) throws ParseException{
return df.get().parse(source);
}
}
```
在线程中采用DateFormatThreadLocal进行转换:
```java
/** 解决多线程问题 */
@Test
public void test1 () throws ExecutionException, InterruptedException {
Callable task = new Callable() {
@Override
public Date call() throws Exception {
return DateFormatThreadLocal.convert("20161121");
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List> results = new ArrayList<>();
for (int i = 0; i < 20; i++) {
results.add(pool.submit(task));
}
for (Future future : results) {
System.out.println(future.get());
}
pool.shutdown();
}
```
执行多次,也不会出现线程安全问题 。
### java8 的DateTimeFormatter可以避免多线程问题
``` java
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
Callable task = new Callable() {
@Override
public LocalDate call() throws Exception {
LocalDate ld = LocalDate.parse("20161121", dtf);
return ld;
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(pool.submit(task));
}
for (Future future : results) {
System.out.println(future.get());
}
pool.shutdown();
```