Java高并发程序设计--ThreadLocal

Posted 蒋曾的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java高并发程序设计--ThreadLocal相关的知识,希望对你有一定的参考价值。

如果说锁是让线程有序的争夺资源的话,那么ThreadLocal就是让每个线程都有一份资源。

打个比方,锁是让一百个人争夺一只笔区写字,ThreadLocal就是一百个人每人都有一只笔,在轮到他们写字的时候写。

写个简单的例子:

public class demo implements Runnable{
    static ThreadLocal<test> tl=new ThreadLocal<test>();
    static class test 
    {
        private Integer in;
        public Integer getIn() {return in;}
        test(Integer in){this.in=in;}
    }
    public static void main(String[] args) {
        ExecutorService es=Executors.newFixedThreadPool(10);
        for(int i=0;i<100;i++)
        {
            es.submit(new demo());
        }
    }
    public void run() {
        tl.set(new test(new Random().nextInt(100)));
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(tl.get().getIn());
    }
}

Demo里有一个test内部类,有一百个线程,每个线程都有一个test类存在ThreadLocal那里,每个线程访问自己的test,互不影响。

 

接下来来看ThreadLocal的原理,从set()方法看起:

 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,ThreadLocalMap是它的内部类:

static class ThreadLocalMap {
        static class Entry extends WeakReference<ThreadLocal> {
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }
、、、、、、、、、 }

可以把它看做和HashMap类似的东西,用ThreadLocal作为key,

然后进入getMap()方法:

ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

直接获得线程的threadLocals,进入Thread,

ThreadLocal.ThreadLocalMap threadLocals = null;

可以看到Thread维护了一个ThreadLocal.ThreadLocalMap,回到set方法,现在我们知道getMap()获得一个有Thread维护的ThreadLocal内部类,现在它为空,进入else,进入createMap():

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

给Thread中的threadLocals赋值,自己本身作为key,需要维护的值作为Value。

 

看完set方法,接下来看get()方法:

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

很简洁明了,从map里面获得value,没什么好说的,想了解更详细的可以自己看源码。

 

另外,因为threadLocals的引用是在Thread里面,Thread不退出,意味着它会一直存在,而且如果是由线程池维护线程,线程可能不会退出。

所以最好习惯性用完之后,调用remove()方法。

 


以上是关于Java高并发程序设计--ThreadLocal的主要内容,如果未能解决你的问题,请参考以下文章

Java——多线程高并发系列之ThreadLocal的使用

java ThreadLocal线程设置私有变量底层源码分析

ThreadLocal个人理解梳理

ThreadLocal学习笔记

ThreadLocal学习笔记

java多线程