SimpleDateFormat非线程安全

枝上柳绵吹又少,天涯何处无芳草
类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;
    }
}

这里写图片描述
使用这两种方法,都没有出现异常,说明异常已经被我们解决了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值