博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java ThreadLocal使用
阅读量:4656 次
发布时间:2019-06-09

本文共 5664 字,大约阅读时间需要 18 分钟。

1、源码分析

此处以JDK1.8版本分析

1.1 set方法

  /**     * Sets the current thread's copy of this thread-local variable     * to the specified value.  Most subclasses will have no need to     * override this method, relying solely on the {
@link #initialValue} * method to set the values of thread-locals. * * @param value the value to be stored in the current thread's copy of * this thread-local. */ public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }

此处的ThreadLocalMap为ThreadLocal的一个内部类,用Entry来存储要设置的值。如下

   static class ThreadLocalMap {        /**         * The entries in this hash map extend WeakReference, using         * its main ref field as the key (which is always a         * ThreadLocal object).  Note that null keys (i.e. entry.get()         * == null) mean that the key is no longer referenced, so the         * entry can be expunged from table.  Such entries are referred to         * as "stale entries" in the code that follows.         */        static class Entry extends WeakReference
> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal
k, Object v) { super(k); value = v; } }   }

看下getMap()方法,用于返回当前ThreadLocal维护的ThreadLocalMap对象,如下

/**     * 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;    }

此处的t.threadLocals为当前Thread维护的ThreadLocalMap对象

  /* ThreadLocal values pertaining to this thread. This map is maintained     * by the ThreadLocal class. */    ThreadLocal.ThreadLocalMap threadLocals = null;

再看下createMap()方法,用于为当前Thread没有ThreadLocalMap时新建一个ThreadLocalMap,如下

  /**     * 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     */    void createMap(Thread t, T firstValue) {        t.threadLocals = new ThreadLocalMap(this, firstValue);    }

从源码中可以看出set方法过程:获取当前线程,并作为句柄去获取ThreadLocalMap,如果ThreadLocalMap存在,则以当前ThreadLocal对象为key,传入的对象为value进行存储。否则新建一个和当前线程相关联的ThreadLocalMap来存储。

1.2 get方法

  /**     * 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) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }

从源码可以看出也是以当前线程为句柄获取ThreadLocalMap对象,如果存在则返回当前线程的ThreadLocal为key对应的值,否则设置初始值setInitialValue

/**     * 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;    }

其中initialValue返回null

/**     * 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 {
@code initialValue} 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}. * *

This implementation simply returns {

@code null}; if the * programmer desires thread-local variables to have an initial * value other than {
@code null}, {
@code ThreadLocal} 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; }

1.3 remove()方法

/**     * Removes the current thread's value for this thread-local     * variable.  If this thread-local variable is subsequently     * {
@linkplain #get read} by the current thread, its value will be * reinitialized by invoking its {
@link #initialValue} method, * unless its value is {
@linkplain #set set} by the current thread * in the interim. This may result in multiple invocations of the * {
@code initialValue} method in the current thread. * * @since 1.5 */ public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }

从源码可以很容易看出remove的作用过程,不做详细分析。为了避免内存泄漏问题,尽量在当前线程处理完之后手动进行remove操作。

2、总结

从上面的源码可以看出ThreadLocal设置的值和线程相关,可以理解为是线程的私有的访问区域,其他线程无法访问,实现了“数据隔离”效果。和解决并发问题和共享变量无关

每个Thread都维护者一个ThreadLocalMap的引用。

转载于:https://www.cnblogs.com/kingsonfu/p/11177666.html

你可能感兴趣的文章
Linux Supervisor的安装与使用入门
查看>>
创建 PSO
查看>>
JasperReport报表设计4
查看>>
项目活动定义 概述
查看>>
团队冲刺04
查看>>
我的Python分析成长之路8
查看>>
泛型在三层中的应用
查看>>
SharePoint2010 -- 管理配置文件同步
查看>>
.Net MVC3中取得当前区域的名字(Area name)
查看>>
获得屏幕像素以及像素密度
查看>>
int与string转换
查看>>
adb命令 判断锁屏
查看>>
推荐一个MacOS苹果电脑系统解压缩软件
查看>>
1035等差数列末项计算
查看>>
CDMA鉴权
查看>>
ASP.NET MVC Identity 兩個多個連接字符串問題解決一例
查看>>
过滤器与拦截器区别
查看>>
第二阶段站立会议7
查看>>
JAVA多线程
查看>>
delphi 更改DBGrid 颜色技巧
查看>>