Android-ThreadLocal

作者: 湘北南 | 来源:发表于2019-01-08 17:01 被阅读5次

ThreadLocal简介

ThreadLocal是线程内部的局部变量,保证该变量在线程内部是独立的,我们可以通过set/get方法来设置或者获取变量的值。

根据ThreadLocal结构,我们画了下面一张流程结构图:

ThreadLocal简介图

结构图说明:

1)Thread里面有一个ThreadLocal.ThreadLocalMap的变量threadLocals,threadLocals是一个Map结构,key是ThreadLocal<T>,value是T。

2)假设有两个ThreadLocal变量,分别是ThreadLocal<A> tlA,ThreadLocal<B> tlB。
在线程Thread-1和Thread-2中tlA.set(new A()),tlB.set(new B()),则在线程Thread-1和Thread-2中通过tlA.get(),tlB.get()获取到的分别是相应线程对应的对象A,对象B。

总结:ThreadLocal提供线程的内部变量,只是在该线程的生命周期里起作用。

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 getMap(Thread t) {
        return t.threadLocals;
    }
  void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

说明:我们先拿到当前的线程对象,然后通过线程对象取到线程的ThreadLocalMap对象,即threadLocals,然后分如下两种情况:

1)threadLocals是null,则创建ThreadLocalMap对象,同时将key值和value放到map中;
2)threadLocals非null,则直接设定key值和value值。

我们上面也说到了,threadLocals是一个ThreadLocal.ThreadLocalMap类型的Map结构,key是ThreadLocal<T>,value是T。

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();
    }
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;
    }
 protected T initialValue() {
        return null;
    }

说明:get方法我们先拿到当前的线程对象,然后通过线程对象取到线程的ThreadLocalMap对象,即threadLocals,然后也分如下两种情况:

1)threadLocals是null,则创建ThreadLocalMap对象,同时设定一个初始值;
2)threadLocals非null,则直接以当前的ThreadLocal<T>对象取到value并返回。

ThreadLocal例子

ThreadLocal的例子很简单,我们声明了两个ThreadLocal变量,然后分别在主线程,两个子线程里面通过set方法设定对象的值,并在相应的线程里面通过get方法输出对象的hashcode,代码如下:

public class ThreadLocalTest {
    private static ThreadLocal<A> tlA = new ThreadLocal<>();
    private static ThreadLocal<B> tlB = new ThreadLocal<>();
    public static class A {
        @Override
        public String toString() {
            return A.class.getSimpleName() + ":" + Integer.toHexString(hashCode());
        }
    }
    public static class B {
        @Override
        public String toString() {
            return B.class.getSimpleName() + ":" + Integer.toHexString(hashCode());
        }
    }
    public static class ThlRunnable implements Runnable {
        @Override
        public void run() {
            tlA.set(new A());
            tlB.set(new B());
            System.out.println("ThreadName:" + Thread.currentThread().getName() + ","
                    + tlA.get().toString() + "," + tlB.get().toString() );

        }
    }
    public static void main(String[] args) {
        tlA.set(new A());
        tlB.set(new B());
        for (int i = 0; i < 2; i++) {
            new Thread(new ThlRunnable()).start();
        }

        System.out.println("ThreadName:" + Thread.currentThread().getName() + ","
                + tlA.get().toString() + "," + tlB.get().toString() );
        System.exit(0);

    }
}

输出结果:

ThreadName:Thread-1,A:5012d748,B:5ed5333a
ThreadName:main,A:3feba861,B:5b480cf9
ThreadName:Thread-2,A:18cf66fa,B:16089b93

每个线程获取的对象结果都是不一样,因此,通过ThreadLocal,我们保证了同一类型的不同对象在各个线程之间的独立性。

相关文章

  • Android-ThreadLocal

    简介 threadlocal是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存...

  • Android-ThreadLocal

    ThreadLocal简介 ThreadLocal是线程内部的局部变量,保证该变量在线程内部是独立的,我们可以通过...

  • Android-ThreadLocal

    概述 ThreadLocal用于保存线程作用域内的对象;对象是线程共享的,所以为了达到线程之间使用不同的对象,使用...

  • Android-ThreadLocal解析

    ThreadLocal分析 Handler的运行需要MessageQueue和Looper的支持,如果您对这方面不...

网友评论

    本文标题:Android-ThreadLocal

    本文链接:https://www.haomeiwen.com/subject/vorprqtx.html