zoukankan      html  css  js  c++  java
  • 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()方法。

  • 相关阅读:
    python基础练习5-9
    python安装
    python虚拟环境
    python基础语法--逻辑实现
    python基础语法
    IDE(vscode)
    pycharm使用
    复习
    环境搭建+python基础
    ASP.NET 5行代码搞二维码
  • 原文地址:https://www.cnblogs.com/blogofjzq/p/9437344.html
Copyright © 2011-2022 走看看