枝上柳绵吹又少,天涯何处无芳草
类SimpleDateFormat主要负责日期的转换与格式化,但是在多线程的环境下,使用此类容易造成数据转换及处理的不正确,因为SimpleDateFormat类并不是线程安全的。
测试代码:
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[] dateStringArray = new String[]{"2000-01-01","2000-06-01","2000-06-01","2000-11-05","2000-08-01","2014-06-01","2018-10-01","2001-11-05","2013-08-01","2013-08-21"};
MyThread[] myThreads = new MyThread[10];
for (int i = 0 ;i < myThreads.length; i++) {
myThreads[i] = new MyThread(sdf,dateStringArray[i]);
}
for (int i = 0 ;i < 10; i++) {
myThreads[i].start();
}
}
}
class MyThread extends Thread {
private SimpleDateFormat sdf;
private String dateString;
public MyThread(SimpleDateFormat sdf,String dateString) {
super();
this.sdf = sdf;
this.dateString = dateString;
}
@Override
public void run() {
try {
Date dateRef = sdf.parse(dateString);
String newDateString = sdf.format(dateRef).toString();
if (!newDateString.equals(dateString)) {
System.out.println("ThreadName=" + this.getName() + "报错了,日期字符串:" + dateString + "转成的日期为:" + newDateString);
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
这样就有很大概率出现转换异常的问题。那么,这个问题如何解决呢?
解决异常方法一:创建多个SimpleDateFormat对象
代码:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[] dateStringArray = new String[]{"2000-01-01","2000-06-01","2000-06-01","2000-11-05","2000-08-01","2014-06-01","2018-10-01","2001-11-05","2013-08-01","2013-08-21"};
MyThread[] myThreads = new MyThread[10];
for (int i = 0 ;i < myThreads.length; i++) {
myThreads[i] = new MyThread(sdf,dateStringArray[i]);
}
for (int i = 0 ;i < 10; i++) {
myThreads[i].start();
}
}
}
class MyThread extends Thread {
private SimpleDateFormat sdf;
private String dateString;
public MyThread(SimpleDateFormat sdf,String dateString) {
super();
this.sdf = sdf;
this.dateString = dateString;
}
@Override
public void run() {
try {
Date dateRef = dateTools.parse("yyyy-MM-dd",dateString);
String newDateString = dateTools.format("yyyy-MM-dd",dateRef).toString();
if (!newDateString.equals(dateString)) {
System.out.println("ThreadName=" + this.getName() + "报错了,日期字符串:" + dateString + "转成的日期为:" + newDateString);
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
class dateTools {
public static Date parse(String formatPattern,String dateSring) throws ParseException {
return new SimpleDateFormat(formatPattern).parse(dateSring);
}
public static String format(String formatPattern,Date date) throws ParseException {
return new SimpleDateFormat(formatPattern).format(date);
}
}
运行结果:
解决异常方法二:使用ThreadLocal类绑定到指定对象,也可以解决该问题。
测试代码:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[] dateStringArray = new String[]{"2000-01-01","2000-06-01","2000-06-01","2000-11-05","2000-08-01","2014-06-01","2018-10-01","2001-11-05","2013-08-01","2013-08-21"};
MyThread[] myThreads = new MyThread[10];
for (int i = 0 ;i < myThreads.length; i++) {
myThreads[i] = new MyThread(sdf,dateStringArray[i]);
}
for (int i = 0 ;i < 10; i++) {
myThreads[i].start();
}
}
}
class MyThread extends Thread {
private SimpleDateFormat sdf;
private String dateString;
public MyThread(SimpleDateFormat sdf,String dateString) {
super();
this.sdf = sdf;
this.dateString = dateString;
}
@Override
public void run() {
try {
Date dateRef = dateTools.getSimpleDateFormat("yyyy-MM-dd").parse(dateString);
String newDateString = dateTools.getSimpleDateFormat("yyyy-MM-dd").format(dateRef).toString();
if (!newDateString.equals(dateString)) {
System.out.println("ThreadName=" + this.getName() + "报错了,日期字符串:" + dateString + "转成的日期为:" + newDateString);
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
class dateTools {
public static ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<>();
public static SimpleDateFormat getSimpleDateFormat(String formatPattern) {
SimpleDateFormat sdf = null;
if (sdf == null) {
sdf = new SimpleDateFormat(formatPattern);
tl.set(sdf);
}
return sdf;
}
}
使用这两种方法,都没有出现异常,说明异常已经被我们解决了。