`
long_ai_feng
  • 浏览: 2508 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

解决SimpleDateFormat线程不安全问题

    博客分类:
  • java
阅读更多

前言:

SimpleDateFormat不是线程安全的,而且创建一个实例的开销是非常昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。

 

SimpleDateFormat的javadoc中有这么句话:

Synchronization

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.


翻译一下:

*日期格式是不同步的.

* 建议为每个线程创建独立的格式实例.

* 如果多线程并发访问同一个格式,则必须保持外部同步.

目前很多公司使用的是一下两种方式去创建的日期工具类:

 

1、在每个方法里面使用new SimpleDateFormat的形式

public static Date newParse(String strDate) throws ParseException {
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(strDate);
}

 

注:这种方式是能解决线程安全问题,但是产生了性能问题,主要是创建一个 SimpleDateFormat实例的开销比较昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。

 

2、定义一个全局变量

 

private static final SimpleDateFormat datetimeFormat = 
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 格式化日期与时间
     */
    public static String formatDatetime(long timestamp) {
        return datetimeFormat.format(new Date(timestamp));
    }

 

 注:这种方式是解决了性能问题,但是没有解决线程安全问题,在多线程环境下,容易发生各种意想不到的问题,如:java.lang.NumberFormatException: multiple points或者java.lang.NumberFormatException: For input string: ""等异常。

 

解决此问题有两种方式:

1、使用Threadlocal

 

    private static final ThreadLocal<SimpleDateFormat>	_threadLocal	= new ThreadLocal<SimpleDateFormat>() {
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat();
        }
    };

    /**
     * 格式化日期与时间
     */
    public static String formatDatetime(long timestamp) {
        return _threadLocal.get().format(new Date(timestamp));
    }

 

2、使用享元模式

A、创建SimpleDateFormatFactory类

public class SimpleDateFormatFactory {

    private static final ThreadLocal<Map<String, SimpleDateFormat>>	_threadLocal	= new ThreadLocal<Map<String, SimpleDateFormat>>() {
        protected Map<String, SimpleDateFormat> initialValue() {
            return new HashMap<String, SimpleDateFormat>();
        }
    };

    public static SimpleDateFormat getInstance() {
        return getInstance(DateUtil.DATE_FORMAT);
    }

    public static SimpleDateFormat getInstance(String format) {
        SimpleDateFormat sdf = _threadLocal.get().get(format);
        if (null == sdf) {
            sdf = new SimpleDateFormat(format);
            _threadLocal.get().put(format, sdf);
        }
        return sdf;
    }
}

 

B、DateUtil类

 

public class DateUtil {

/**
     * 显示日期的格式,yyyy-MM-dd
     */
    public static final String DATE_FORMAT = "yyyy-MM-dd";

/**
     * DateFormat,格式:yyyy-MM-dd
     */
    private static DateFormat dateFormat;

static {
        dateFormat = SimpleDateFormatFactory.getInstance(DATE_FORMAT);
         }


   /**
     * 格式化日期与时间
     */
    public static String formatDatetime(long timestamp) {
        return dateFormat.format(new Date(timestamp));
    }

}

 

优点:可以更好的去减少系统中对象的个数和对外部状态相对独立等好处。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics