Java并发(三) ThreadLocal关键字

TheadLocal称为线程本地存储,就是说一个变量,每个线程都有它的一个副本,并且相互之间是独立的。

ThreadLocal类的实现

下面是该类的提供的关键的几个方法:

public T get() { }
public void set(T value) { }
public void remove() { }
protected T initialValue() { }

通过查看jdk中该类的源码,可以大致看到上述方法的实现,其中:

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

是get()方法的实现,首先是通过一个getMap得到ThreadLocalMap,然后在这个ThreadLocalMap中通过this来获得对应的值作为返回值:如果将ThreadLocalMap看作map的话,我们可以发现实际上这个map的key是当前的ThreadLoca变量。
接下来看getMap方法的实现

    /**
     * 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,该变量是一个ThreadLocalMap类型。

这样我们就可以总结出TheadLocal大致的工作原理:有依附于每个线程的一个ThreadLocalMap的类似map的数据结构,这个数据结构的key就是我们定义的ThreadLocal变量,同时我们可以定义多个ThreadLocal变量作为这个map的key。
用图形表示为:
这里写图片描述
从这里来看,ThreadLocal其实只是相当于声明了某种类型是线程本地存储,实际上的数据是存储在每个Thread实例的成员变量中的。这也就是线程本地存储名称的来源—数据实际上存储在本地线程中。
另外还有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);
    }

用于修改value值。

另外注意到,ThreadLocalMap中的内部类Entry是声明为WeakReference,这是java中的四种Reference类型之一。通过相关相关书籍和网页,简单介绍一下:
StrongReference,就是我们通常通过new Object()这样的形式得到的引用,叫强引用,只要强引用还在,GC就不会回收相应的对象。
SoftReference,软引用,系统在内存将要溢出之前,会对这类引用的对象进行清理。比如外部数据源:文件、数据库、网络等可声明为该类型引用。
WeakReference,弱引用,被弱引用关联的对象如果被JVM识别为弱可达,那么在下次GC的时候就会进行回收。
SoftReference与WeakReference的区别是GC的时间是尽量推迟的。
Phantom,虚引用。不能通过虚引用来获得一个对象实例,唯一的目的是在对象被回收时得到一个系统通知。

ThreadLocal应用场景

数据库连接、Session管理等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值