ThreadLocal使用代码欣赏

    xiaoxiao2021-03-25  160

    使用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; }
    转载请注明原文地址: https://ju.6miu.com/read-4815.html

    最新回复(0)