SimpleDateFormat多线程下的异常

  今天在生产上碰到一个怪异的问题,之前一直跑的很好的xml转object程序,在日期转化的过程中报错的,经过排查原因,原来是由于SimpleDateFormat在多线程下运行造成的结果。
demo例子如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*日期格式化
**/
public class DateFormat {
    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");

    public Date parseDate(String str ){
        if(str == null)
            return null;
        try {
            return SDF.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

}



public class Test {

    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    DateFormat sdf = new DateFormat();
                    System.out.println(sdf.parseDate("2016-10-19"));
                }
            });
            thread.start();
        }
    }
}

运行错误信息:

Exception in thread "Thread-4" Exception in thread "Thread-3" java.lang.NumberFormatException: For input string: "..10011001EE22"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Long.parseLong(Long.java:430)
    at java.lang.Long.parseLong(Long.java:483)
    at java.text.DigitList.getLong(DigitList.java:194)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1316)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
    at java.text.DateFormat.parse(DateFormat.java:355)
    at com.busap.DateFormat.parseDate(DateFormat.java:14)
    at com.busap.Abc$1.run(Abc.java:19)
    at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-2" java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1110)
    at java.lang.Double.parseDouble(Double.java:540)
    at java.text.DigitList.getDouble(DigitList.java:168)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
    at java.text.DateFormat.parse(DateFormat.java:355)
    at com.busap.DateFormat.parseDate(DateFormat.java:14)
    at com.busap.Abc$1.run(Abc.java:19)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1110)
    at java.lang.Double.parseDouble(Double.java:540)
    at java.text.DigitList.getDouble(DigitList.java:168)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
    at java.text.DateFormat.parse(DateFormat.java:355)
    at com.busap.DateFormat.parseDate(DateFormat.java:14)
    at com.busap.Abc$1.run(Abc.java:19)
    at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-3" java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Long.parseLong(Long.java:453)
    at java.lang.Long.parseLong(Long.java:483)
    at java.text.DigitList.getLong(DigitList.java:194)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1316)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
    at java.text.DateFormat.parse(DateFormat.java:355)
    at com.busap.DateFormat.parseDate(DateFormat.java:14)
    at com.busap.Abc$1.run(Abc.java:13)
    at java.lang.Thread.run(Thread.java:745)

各种异常接踵而至,原因就是SimpleDateFormat不是线程安全类。要想解决上述问题,去掉static final 修饰符,这样每个线程生成一个SimpleDateFormat,线程之间互不影响就解决了上面的问题。不过如果在大并发的情况,就会生成一堆SimpleDateFormat类(static final 修饰符原意也是为了解决这个问题),为了优化大并发的情况,可以使用ThreadLocal。在同一个线程内共享一个SimpleDateFormat,总比多次调用生成多个的好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值