Android开发经验谈Android开发程序员

ThreadLocal介绍

2017-09-06  本文已影响296人  选一个昵称这么难

我们在说明handler原理和AsyncTask原理的时候都提到了ThreadLocal,当时没有细说,现在来介绍一下这个类
ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其它线程来说无法获取到数据.
什么意思?看代码更明白

public class MainActivity extends AppCompatActivity {

    //这里的泛型我们使用String,具体使用什么跟实际需求有关
    private ThreadLocal<String> threadLocal;
    private ThreadLocal<Integer> threadLocal2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        threadLocal = new ThreadLocal<>();
        threadLocal2 = new ThreadLocal<>();
        threadLocal.set("main");
        final Thread thread1 = new Thread(){
            @Override
            public void run() {
                threadLocal.set("1");
                threadLocal2.set(1111111);
                System.out.println(Thread.currentThread().getName()+"   :"+threadLocal.get());
                System.out.println(Thread.currentThread().getName()+"   :"+threadLocal2.get());
            }
        };

        final Thread thread2 = new Thread(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"   :"+threadLocal.get());
            }
        };

        thread1.setName("线程1");
        thread2.setName("线程2");
        thread1.start();
        thread2.start();
        System.out.println(Thread.currentThread().getName()+"   :"+threadLocal.get());
    }
}

查看结果:

System.out: 线程1   :1
System.out: main   :main
System.out: 线程2   :null
System.out: 线程1   :1111111

分析:虽然只有一个ThreadLocal实例,但是我们在不同线程为其赋值,然后在各自线程得到自己赋的值,这就很好的说明了ThreadLocal的特点
线面通过源码看看为什么会这样
先看set()方法

public void set(T value) {
        Thread t = Thread.currentThread();
        //getMap()方法就一句话:t.threadLocals,这个值默认是null
        //每个线程都维护了一个ThreadLocalMap,简单说ThreadLocalMap就是一个最终用来存储的容器
        ThreadLocalMap map = getMap(t);
        if (map != null)
            //key值是ThreadLocal对象,因为我们可以创建多个ThreadLocal对象来存储不同的数据,
            // value是设置的值
            map.set(this, value);
        else
            //创建ThreadLocalMap并存储
            createMap(t, value);
    }

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

看到这,应该明白ThreadLocal的奥秘了吧

上一篇 下一篇

猜你喜欢

热点阅读