SimpleDateFormat的并发安全工具类

  多线程环境下SimpleDateFormat调用format和parse时共享Calendar变量,会引发线程安全问题。使用锁太影响效率,可以使用ThreadLocal解决线程安全问题。

工具类代码如下:

public class DateFormatFactory {
    private static final Map<String, ThreadLocal<SimpleDateFormat>> pool = new HashMap();
    private static final Object lock = new Object();

    public DateFormatFactory() {
    }

    /**
     * @author ztt
     * @Date:2019/9/14
     * @param pattern
     */
    public static SimpleDateFormat getDateFormat(final String pattern) {
        ThreadLocal<SimpleDateFormat> t1 = (ThreadLocal) pool.get(pattern);
        if (t1 == null) {
            synchronized (lock) {
                t1 = (ThreadLocal) pool.get(pattern);
                if (t1 == null) {
                    synchronized (lock) {
                        t1 = ThreadLocal.withInitial(() -> new SimpleDateFormat(pattern));
                    }
                    pool.put(pattern, t1);
                }
            }
        }
        return (SimpleDateFormat) t1.get();
    }

    public static void clear(){
        synchronized (lock){
            pool.values().forEach(ThreadLocal::remove);
        }
    }

}
View Code

调用使用如下:

SimpleDateFormat dataFormat = DateFormatFactory.getDateFormat("MMddHHmmss");
        String timeStr =dataFormat.format(Calendar.getInstance().getTime());
View Code

代码解析:

DateFormatFactory.getDateFormat("MMddHHmmss");

DateFormatFactory调用静态方法getDateFormat获取私有静态类Map类型的t1中key为"MMddHHmmss"的value中的SimpleDateFormat变量。

用双检锁单例模式获取t1,t1 = ThreadLocal.withInitial(() -> new SimpleDateFormat(pattern));这个语句说明t1为SuppliedThreadLocal类型的变量。

SuppliedThreadLocal是ThreadLocal的子类,t1.get()时调用initvalue方法。SuppliedThreadLocal中重写了initvalue方法return supplier.get()。

Supplier是函数式接口。所以直接调用到了new SimpleDateFormat(pattern)。返回SimpleDateFormat的同时在当前线程的ThreadLocalMap中存放一份。

 

 

 

 

posted on 2021-09-17 13:00  风中的四月  阅读(87)  评论(0)    收藏  举报