SimpleDateFormat的线程安全性

来源:互联网 发布:js监听视频播放状态 编辑:程序博客网 时间:2024/05/17 01:37

SimpleDateFormat 是线程不安全类,在定义为static时可能出现线程安全问题;推荐使用DateUtils工具类。下面的示例将给出错误的和正确的代码。

首先是错误的代码,执行Demo会发现,在某些竞态条件下报错。

package wrong;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;/** * Created by Administrator on 2016/10/25. */public class MyThread extends Thread {    private String dateString;    private SimpleDateFormat simpleDateFormat;    public MyThread(String dateString, SimpleDateFormat simpleDateFormat) {        super();        this.dateString = dateString;        this.simpleDateFormat = simpleDateFormat;    }    @Override    public void run() {        Date dateRef = null;        try {            dateRef = simpleDateFormat.parse(dateString);            String newDateString = simpleDateFormat.format(dateRef).toString();            if (!newDateString.equals(dateString))                System.out.println("thread" + this.getName() + "报错了 字符串=" + dateString + " 转换成" + newDateString);        } catch (ParseException e) {            e.printStackTrace();        }    }}package wrong;import java.text.SimpleDateFormat;public class Demo {    static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");    public static void main(String[] args) {        String[] dateStringArray = new String[]{                "2000-01-01", "2001-01-01", "2002-01-01", "2003-01-01", "2004-01-01",                "2005-01-01", "2006-01-01", "2007-01-01", "2008-01-01", "2009-01-01"        };        MyThread[] myThreads = new MyThread[10];        for (int i = 0; i < 10; i++) {            myThreads[i] = new MyThread(dateStringArray[i],simpleDateFormat);        }        for (int i = 0; i < 10; i++)            myThreads[i].start();    }}


下面是正确的代码,利用了ThreadLocal的特性,保证每个线程有且只有一个专用的SimpleDateFormat.

package correct;import java.text.ParseException;import java.util.Date;public class MyThread extends Thread {    private String dateString;    public MyThread( String dateString) {        super();        this.dateString = dateString;    }    @Override    public void run() {        Date dateRef = null;        try {            dateRef = DateUtils.getSimpleDateFormat("yyyy-MM-dd").parse(dateString);            String newDateString = DateUtils.getSimpleDateFormat("yyyy-MM-dd").format(dateRef).toString();            if (!newDateString.equals(dateString))                System.out.println("thread" + this.getName() + "报错了 字符串=" + dateString + " 转换成" + newDateString);        } catch (ParseException e) {            e.printStackTrace();        }    }}package correct;import java.text.SimpleDateFormat;/** * Created by Administrator on 2016/10/25. */public class DateUtils {    private static ThreadLocal<SimpleDateFormat> simpleDateFormatThreadLocal=new ThreadLocal<SimpleDateFormat>();    public static SimpleDateFormat getSimpleDateFormat(String pattern){        if(simpleDateFormatThreadLocal.get()==null)            simpleDateFormatThreadLocal.set(new SimpleDateFormat(pattern));        return simpleDateFormatThreadLocal.get();    }}package correct;public class Demo {    public static void main(String[] args) {        String[] dateStringArray = new String[]{                "2000-01-01", "2001-01-01", "2002-01-01", "2003-01-01", "2004-01-01",                "2005-01-01", "2006-01-01", "2007-01-01", "2008-01-01", "2009-01-01"        };        MyThread[] myThreads = new MyThread[10];        for (int i = 0; i < 10; i++) {            myThreads[i] = new MyThread(dateStringArray[i]);        }        for (int i = 0; i < 10; i++)            myThreads[i].start();    }}

SimpleDateFormat的线程安全性是编码时一个常见的坑,要注意正确使用。



0 0
原创粉丝点击