问题描述:
多线程下,使用SimpleDateFormat会有如下异常报错信息:(多次执行以下代码,可以得到以下3种结果。)
- case1: java.lang.NumberFormatException: multiple points
- case2: 错误的结果
- case3: java.lang.NumberFormatException: For input string: “”
代码如下:
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 10个线程同时调用一个SimpleDateFormat实例格式化日期字符串
*/
public class SimpleDateFormatTest {
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date format(String str) {
Date s = null;
try {
s = sdf.parse(str);
System.out.println(Thread.currentThread().getName() + ":" + s.toString());
} catch (ParseException e) {
e.printStackTrace();
}
return s;
}
@Test
public void test1() {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
format("20200816");
},"Thread"+i).start();
}
}
}
解决方案:
- 每次都实例化一个SimpleDateFormat,当调用format()的时候。
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
- 使用ThreadLocal
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 10个线程同时调用一个SimpleDateFormat实例格式化日期字符串
*/
public class SimpleDateFormatTest {
private static final String DATE_FORMATTER = "yyyyMMdd";
private static ThreadLocal<SimpleDateFormat> sdf = new ThreadLocal<>();
private SimpleDateFormat getDateFormat() {
SimpleDateFormat format = sdf.get();
if (null == format) {
format = new SimpleDateFormat(DATE_FORMATTER);
sdf.set(format);
}
return format;
}
Date format(String str) {
Date s = null;
try {
s = getDateFormat().parse(str);
System.out.println(Thread.currentThread().getName() + ":" + s.toString());
} catch (ParseException e) {
e.printStackTrace();
}
return s;
}
@Test
public void test1() {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
format("2020-08-16");
},"Thread"+i).start();
}
}
}