zoukankan      html  css  js  c++  java
  • ThreadLocal

    ThreadLocal不是一个线程类,无法像Thread一样调用start()创建多线程,严格意义上说是一个线程局部变量,源码上有以下说明

    /**
    *This class provides thread-local variables. These variables differ from
    *their normal counterparts in that each thread that accesses one (via its
    *{@code get} or {@code set} method) has its own, independently initialized
    *copy of the variable.  {@code ThreadLocal} instances are typically private
    *static fields in classes that wish to associate state with a thread (e.g.,
    *a user ID or Transaction ID).
    ...
    */
    

    简单来说,ThreadLocal的作用是在每个线程开辟一个属于线程的空间存储所需变量的副本,实现变量的线程隔离。以空间来换时间,在某些情况下,这种共享变量的实现方式更有效率,在spring中被使用在singleton模式中。

    实现原理

    由于ThreadLocal不是线程类,没有任何继承和依赖,没有相关的接口和抽象类。

    public class ThreadLocal<T> 
    

    它的底层实现其实很简单,利用的是map,但是这个map不是利用HashMap类,而是重写了一个ThreadLocalMap,具体的源码就不展示了,主要描述一下过程,在存入变量副本的过程中,以每个线程作为key,变量副本作为value的形式存入到ThreadLocalMap中,取出的时候也是和hashmap一样。

    set(T value)

    set方法主要是将变量副本存入到ThreadLocalMap中,源码如下

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //如果存在ThreadLocalMap,那么set方法插入变量备份
        if (map != null)
            map.set(this, value);
        //不存在,就创建ThreadLocalMap
        else
            createMap(t, value);
    }
    

    get()

    get方法是获取变量副本的,由于每个线程只存一个,就不存在通过key去区分,所以get方法没有参数,源码如下

    public T get() {
        Thread t = Thread.currentThread();
        //根据当前线程获取ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);//获取Entry
            //如果不为空,就获取value
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        //否则获取默认初始值
        return setInitialValue();
    }
    

    常用方法

    • private T setInitialValue(),主要用于加上默认初始值,这样在未开辟当前线程空间之前get获得的都是默认初始值
    • public void remove(),移除当前线程的开辟区域

    内存泄漏问题

    这里需要注意ThreadLocal底层实现是通过一个map实现的,属于Java类,因此,它也属于Java的垃圾回收gc,因此当ThreadLocal变量为null时,可以被回收,但是那些value却不会被回收,因为存在一条从当前线程连接过来的强引用。只有当前线程结束以后,不会存在栈中,强引用才会断开,value才会全部被gc回收。

  • 相关阅读:
    H3C交换机删除VLAN与其绑定端口配置
    H3CNE实验:配置交换机接口
    在H3C交换机上开通一个VLAN并且开通一个端口ping通它
    局域网交换技术知识点
    Java开发中常用的设计模式(二)---单例模式
    Java开发中常用的设计模式(一)---工厂模式
    DevExpress13.2.9 控件使用经验总结
    基于.Net下整合RestSharp,实现REST服务客户端
    基于.Net下整合FastReport,实现条码标签批量打印
    基于.Net下整合IBatis
  • 原文地址:https://www.cnblogs.com/xudilei/p/6858122.html
Copyright © 2011-2022 走看看