SimpleDateFormat非线程安全
类SimpleDateFormat主要负责日期的格式化和转换,但是在多线程的环境中,使用此类容易造成数据转换和处理不正确,因为SimpleDateFormat类并不是线程安全的。
- 1简单示例,出现异常
package com.test.test4;
import java.text.SimpleDateFormat;
/**
* SimpleDateFormat非线程安全
* Created by admin on 2018/12/18.
*/
public class Test {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[]dataStringArray = new String[]{"2000-01-01","2000-01-02","2000-01-03","2000-01-04","2000-01-05"};
MyThread[] threadArray = new MyThread[5];
for (int i=0;i<5;i++) {
threadArray[i] = new MyThread(sdf,dataStringArray[i]);
}
for (int i=0;i<5;i++) {
threadArray[i].start();
}
}
}
package com.test.test4;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by admin on 2018/12/18.
*/
public 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 (ParseException e) {
e.printStackTrace();
}
}
}
- 运行结果
ThreadName=Thread-4报错了 日期字符串:2000-01-05转换成的日期为0001-01-02 ThreadName=Thread-2报错了 日期字符串:2000-01-03转换成的日期为0001-01-02 ThreadName=Thread-0报错了 日期字符串:2000-01-01转换成的日期为0001-01-02 ThreadName=Thread-3报错了 日期字符串:2000-01-04转换成的日期为0001-01-02 Process finished with exit code 0
- 解决异常办法一:解决处理错误的原理是创建了多个SimpleDateFormat
public class Test {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[]dataStringArray = new String[]{"2000-01-01","2000-01-02","2000-01-03","2000-01-04","2000-01-05"};
MyThread[] threadArray = new MyThread[5];
for (int i=0;i<5;i++) {
threadArray[i] = new MyThread(sdf,dataStringArray[i]);
}
for (int i=0;i<5;i++) {
threadArray[i].start();
}
}
}
package com.test.formatOk1;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by admin on 2018/12/18.
*/
public class DateTools {
public static Date parse(String formatPattern, String dataString) throws ParseException{
return new SimpleDateFormat(formatPattern).parse(dataString);
}
public static String format(String formatPattern,Date date){
return new SimpleDateFormat(formatPattern).format(date).toString();
}
}
package com.test.formatOk1;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by admin on 2018/12/18.
*/
public 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 (ParseException e) {
e.printStackTrace();
}
}
}
解决异常办法二:ThreadLocal类能使线程绑定到指定对象,使用ThreadLocal也可以处理这种错误
package com.test.formatOk2;
import java.text.SimpleDateFormat;
/**
* SimpleDateFormat非线程安全
* Created by admin on 2018/12/18.
*/
public class Test {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[]dataStringArray = new String[]{"2000-01-01","2000-01-02","2000-01-03","2000-01-04","2000-01-05"};
MyThread[] threadArray = new MyThread[5];
for (int i=0;i<5;i++) {
threadArray[i] = new MyThread(sdf,dataStringArray[i]);
}
for (int i=0;i<5;i++) {
threadArray[i].start();
}
}
}
package com.test.formatOk2;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by admin on 2018/12/18.
*/
public class DateTools {
private static ThreadLocal<SimpleDateFormat> t1 = new ThreadLocal<SimpleDateFormat>();
public static SimpleDateFormat getSimpleDateFormat(String datePattern){
SimpleDateFormat sdf = null;
sdf = t1.get();
if (sdf == null) {
sdf = new SimpleDateFormat(datePattern);
t1.set(sdf);
}
return sdf;
}
}
package com.test.formatOk2;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by admin on 2018/12/18.
*/
public 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 (ParseException e) {
e.printStackTrace();
}
}
}
浙公网安备 33010602011771号