ThreadLocal原理

本文详细解析了ThreadLocal的工作原理,包括其如何实现线程变量隔离,避免多线程环境下的共享变量冲突。通过具体代码示例,展示了ThreadLocal的使用方式,并深入探讨了其内部实现机制,如ThreadLocalMap的作用及内存泄漏的预防策略。

概念

ThreadLocal并不是用来解决多线程下的共享变量问题,而是提供县城内的线程访问。在多线程环境下,可以保证各个线程之间的变量相互隔离。

使用

public class ThreadLocalDemo implements Runnable{
    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
    public void run(){
        for (int i = 0; i < 3; i++) {
            threadLocal.set(i);
            System.out.println(Thread.currentThread().getName()+",value="+threadLocal.get());
        }
    }

    public static void main(String[] args) {
        ThreadLocalDemo demo = new ThreadLocalDemo();
        new Thread(demo).start();
        new Thread(demo).start();
    }


}

实现原理

ThreadLocalMap是ThreadLocal内部类,有ThreadLocal创建,每一个Thread维护了一个ThreadLocal.ThreadLocalMap类型的属性threadLocals。所有的值都是存储在ThreadLocalMap中。

放入值

    public void set(T value) {
    	//获取当前线程
        Thread t = Thread.currentThread();
        //从当前线程中获取threadLocals
        ThreadLocalMap map = getMap(t);
        if (map != null)
        	//如果当前map不为空,说明之前创建过,以当前线程为key,将值存入其中
            map.set(this, value);
        else
        	//如果没有,那就创建
            createMap(t, value);
    }

获取值

    public T get() {
    	//获取当前线程
        Thread t = Thread.currentThread();
        //从当前线程中获取threadLocals
        ThreadLocalMap map = getMap(t);
        if (map != null) {
        	//如果map不为null,获取key为当前线程的值
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        //如果map为null,返回初始值,这个方法时一个
        return setInitialValue();
    }

	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;
    }
    //如果需要初始值,可以继承ThreadLocal,自己实现这个方法,返回一个初始化值
    protected T initialValue() {
        return null;
    }

移除

     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

内存泄漏问题

在获取值的get方法中,Entry类继承了WeakReference,即每个Entry对象都有一个ThreadLocal的弱引用,GC对弱引用采取的是积极的内存回售策略,避免了无人搭理时内存泄漏。

static class Entry extends WeakReference<ThreadLocal<?>> {

ThreadLocal对象只是作为ThreadLocalMap的一个key值而存在,现在他被回收了,那么value呢?针对这一问题,ThreadLocalMap类在每次set,get,remove的时候,会自动清理key值为null的value。如此一来,value就会被回收了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值