SimpleDateFormat并发问题解决方案

SimpleDateFormat经常被声明为static,在并发环境下公用一个实例,由于它不是线程安全的会产生两种问题:1.日期并不是预想的日期,乱七八糟的任何日期都可能出现。 2. 一定几率下抛异常。
所以有人就每次调用格式化都重新new一个SimpleDateFormat实例,这种方式会存在性能问题,因为其实例化是“expensive”的。所以最优的解决方案是采用ThreadLocal方式。代码如下:


/**
 * TheadLocal SimpleDateFormat
 * Fix SimpleDateFormat concurrency problems and increase performance
 *
 * Date date = ConcurrentDateFormat.getInstance("yyyy-MM-dd HH:mm:ss").parse("2015-10-14 15:29:00");
 * String dateStr = ConcurrentDateFormat.getInstance("yyyy-MM-dd").format(new Date());
 *
 * @author chouzi
 */
public class ConcurrentDateFormat {
    private SimpleDateFormat dateFormat;
    private Locale locale;
    private static ThreadLocal> dateFormatThreadLocal = new ThreadLocal>();

    private ConcurrentDateFormat(SimpleDateFormat df, Locale locale) {
        this.dateFormat = df;
        this.locale = locale;
    }

    public String format(Date date) {
        return dateFormat.format(date);
    }

    public String format(Object date) {
        return dateFormat.format(date);
    }

    /**
     * Returns a String object which formated by
     * the specified number of milliseconds since the
     * standard base time known as "the epoch", namely January 1,
     * 1970, 00:00:00 GMT.
     *
     * @param date the milliseconds since January 1, 1970, 00:00:00 GMT.
     */
    public String format(long date) {
        return dateFormat.format(new Date(date));
    }

    public Date parse(String date) throws ParseException {
        return dateFormat.parse(date);
    }

    /**
     * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
     * represented by this String object.
     *
     * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
     * represented by this string date.
     */
    public long parseToLong(String source) throws ParseException {
        return parse(source).getTime();
    }

    public static ConcurrentDateFormat getInstance(String pattern) {
        return getInstance(pattern, TimeZone.getDefault(), Locale.getDefault());
    }

    public static ConcurrentDateFormat getInstance(String pattern, TimeZone timeZone, Locale locale) {
        if (pattern == null || locale == null) {
            throw new NullPointerException("Parameter pattern or locale must be not null!");
        }

        Map formatMap = dateFormatThreadLocal.get();
        if (formatMap == null) {
            formatMap = new HashMap();
            dateFormatThreadLocal.set(formatMap);
        }

        Key key = new Key(pattern, locale);
        ConcurrentDateFormat concurrentDateFormat = formatMap.get(key);
        if (concurrentDateFormat == null) {
            concurrentDateFormat = new ConcurrentDateFormat(new SimpleDateFormat(pattern, locale), locale);
            formatMap.put(key, concurrentDateFormat);
        }

        concurrentDateFormat.setTimeZone(timeZone);
        return concurrentDateFormat;
    }

    public void setTimeZone(TimeZone timeZone) {
        this.dateFormat.setTimeZone(timeZone);
    }

    public TimeZone getTimeZone() {
        return this.dateFormat.getTimeZone();
    }

    public Locale getLocale() {
        return this.locale;
    }

    /**
     * The key for ConcurrentDateFormat
     *
     * @author taugast
     */
    private static class Key {
        String pattern;
        Locale locale;

        Key(String pattern, Locale locale) {
            this.pattern = pattern;
            this.locale = locale;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((locale == null) ? 0 : locale.hashCode());
            result = prime * result + ((pattern == null) ? 0 : pattern.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (this == obj) {
                return true;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }

            Key other = (Key) obj;
            if (locale == null) {
                if (other.locale != null) {
                    return false;
                }
            } else if (!locale.equals(other.locale)) {
                return false;
            }

            if (pattern == null) {
                if (other.pattern != null) {
                    return false;
                }
            } else if (!pattern.equals(other.pattern)) {
                return false;
            }

            return true;
        }
    }

    public static final String YYYY_MM_DD_CN = "yyyy年MM月dd日";
    public static final String MM_DD_CN = "MM月dd日";
    public static final String YYYY = "yyyy";
    public static final String YYYY_MM_DD_HYPHEN = "yyyy-MM-dd";
    public static final String YYYY_MM_DD_SLASH = "yyyy/MM/dd";
    public static final String HH_MM = "HH:mm";
    public static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
}

 

 

 

 

 

你可能感兴趣的:(java,java)