关于SimpleDateFormat的线程安全问题和解决方案_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 关于SimpleDateFormat的线程安全问题和解决方案

关于SimpleDateFormat的线程安全问题和解决方案

 2015/4/8 12:17:28  maisen  程序员俱乐部  我要评论(0)
  • 摘要:首先简单说一下SimpleDateFormat存在线程安全问题的原因。SimpleDateFormat继承了DateFormat类,类中有一个受保护类型的Calendar对象,再看一下SimpleDateFormat的format方法:privateStringBufferformat(Datedate,StringBuffertoAppendTo,FieldDelegatedelegate){//Convertinputdatetotimefieldlistcalendar.setTime
  • 标签:解决方案 for 解决 问题 线程安全 线程

? ? 首先简单说一下SimpleDateFormat存在线程安全问题的原因。SimpleDateFormat继承了DateFormat类,类中有一个受保护类型的Calendar对象,再看一下SimpleDateFormat的format方法:

class="java" name="code">private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        // Convert input date to time field list
        calendar.setTime(date);

        boolean useDateFormatSymbols = useDateFormatSymbols();

        for (int i = 0; i < compiledPattern.length; ) {
            int tag = compiledPattern[i] >>> 8;
            int count = compiledPattern[i++] & 0xff;
            if (count == 255) {
                count = compiledPattern[i++] << 16;
                count |= compiledPattern[i++];
            }
        ......
}

? ? ?相信大家看到标红的这行代码时,都会明白为什么monospace; line-height: 1.5; background-color: #fafafa;">format方法是非线程安全的了。多个线程共享SimpleDateFormat实例时,对Calendar对象的更改会相互影响,因此产生了线程安全问题。

? ? OK,解决方案:

? ? 1、每当使用时创建一个SimpleDateFormat的实例,但性能会较差(其实以现在jdk的优异表现和软硬件性能的提升,创建SimpleDateFormat实例对性能的影响并不是很明显)。

? ? 2、使用ThreadLocal避免多线程共享实例,代码:

public class ConcurrentDateUtil {

	private static ThreadLocal<DateFormat> DateThreadLocal = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

	private static ThreadLocal<DateFormat> DateTimeThreadLocal = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    public static Date parseDate(String dateStr) throws ParseException {
        return DateThreadLocal.get().parse(dateStr);
    }

    public static String formatDate(Date date) {
        return DateThreadLocal.get().format(date);
    }

    public static Date parseDateTime(String dateStr) throws ParseException {
        return DateTimeThreadLocal.get().parse(dateStr);
    }

    public static String formatDateTime(Date date) {
        return DateTimeThreadLocal.get().format(date);
    }
	
}

? ? ?3、一些其他的方法,比如使用synchronized或第三方工具类,前者对性能影响较大,后者不在本文讨论范围内,大家有时间可以自行研究

发表评论
用户名: 匿名