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

}

  

posted on 2018-12-18 09:12  airycode  阅读(251)  评论(0编辑  收藏  举报

导航