ThreadLocal使用代码欣赏

版权声明:本文为博主总结文章,未经博主允许您依然可以转载。 https://blog.csdn.net/Memery_last/article/details/60876726

使用ThreadLocal可以用来和线程绑定特定的变量,不能被其它的线程使用。来看一个例子:

public class DateUtils {

    public static final String DATE_FMT = "yyyy-MM-dd";

    public static final String DATE_FMT1 = "yyyy-MM-dd HH:mm:ss";

    private static Map<String, ThreadLocal<SimpleDateFormat>> formatMap = Maps.newConcurrentMap();

    public static Date toDate(String date) {
        return toDate(date, DATE_FMT);
    }

    public static Date toDate(String date, String fmt) {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        try {
            final SimpleDateFormat sdf = getFormat(fmt);
            return sdf.parse(date);
        } catch (Exception ex) {
            return null;
        }
    }

    public static String format(Date date) {
        return format(date, DATE_FMT);
    }

    public static String format(Date date, String fmt) {
        if (date == null) {
            return null;
        }
        try {
            final SimpleDateFormat sdf = getFormat(fmt);
            return sdf.format(date);
        } catch (Exception ex) {
            return null;
        }
    }

    public static SimpleDateFormat getFmt(String fmt) {
        return getFormat(fmt);
    }

    private static SimpleDateFormat getFormat(final String fmt) {
        ThreadLocal<SimpleDateFormat> fmtLocal = formatMap.get(fmt);
        if (fmtLocal == null) {
            synchronized (DateUtils.class) {
                fmtLocal = formatMap.get(fmt);
                if (fmtLocal == null) { // Double-Check
                    fmtLocal = new ThreadLocal<SimpleDateFormat>() {
                        @Override
                        protected SimpleDateFormat initialValue() {
                            return new SimpleDateFormat(fmt);
                        };
                    };
                    formatMap.put(fmt, fmtLocal);
                }
            }
        }
        return fmtLocal.get();
    }
}

关注其中的getFormat方法
1)SimpleDateFormat不是线程安全的;
2)定义Map key是dateFormat,value是ThreadLocal对象;
3)使用Double-check的方法为每个线程创建SimpleDateFormat单例;
4)内部类重写ThreadLocal initialValue方法,返回new SimpleDateFormat;
5)调用ThreadLocal get方法获取SimpleDateFormat,具体看ThreadLocal中get方法的实现,及其调用关系;

public class ThreadLocal<T> {
    /**
     * Returns the current thread's "initial value" for this
     * thread-local variable.  This method will be invoked the first
     * time a thread accesses the variable with the {@link #get}
     * method, unless the thread previously invoked the {@link #set}
     * method, in which case the <tt>initialValue</tt> method will not
     * be invoked for the thread.  Normally, this method is invoked at
     * most once per thread, but it may be invoked again in case of
     * subsequent invocations of {@link #remove} followed by {@link #get}.
     *
     * <p>This implementation simply returns <tt>null</tt>; if the
     * programmer desires thread-local variables to have an initial
     * value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be
     * subclassed, and this method overridden.  Typically, an
     * anonymous inner class will be used.
     *
     * @return the initial value for this thread-local
     */
    protected T initialValue() {
        return null;
    }
    /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

    /**
     * Get the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param  t the current thread
     * @return the map
     */
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
    /**
     * Variant of set() to establish initialValue. Used instead
     * of set() in case user has overridden the set() method.
     *
     * @return the initial value
     */
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
    /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     * @param map the map to store.
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
}

6)threadLocals为 Thread类中的属性,由ThreadLocal类来维护。

public
class Thread implements Runnable {
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
}

猜你喜欢

转载自blog.csdn.net/Memery_last/article/details/60876726