为每一个线程提供变量的副本,实现了线程的隔离,也可以保证线程的安全性。
和ThreadLocal相关类- ThreadLocal内部类ThreadLocalMap
- ThreadLocalMap.Entry ThreadLocalMap内部类
- Thread类
ThreadLocal是一个带泛型的类
public class ThreadLocal源码分析{}
Android中最典型用到ThreadLocal地方在Looper里
public final class Looper {
static final ThreadLocal sThreadLocal = new ThreadLocal();
public static void loop() {
final Looper me = myLooper();
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
sThreadLocal.get();源码解析
//泛型T为Looper,我们都会把T 替换成Looper public class ThreadLocal总结{ public Looper get() { Thread t = Thread.currentThread(); //第一步: 通过getMap(t)获取一个ThreadLocalMap ThreadLocalMap map = getMap(t); //第一次进来这个map肯定为null if (map != null) { //ThreadLocalMap.getEntry,获取缓存 ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") Looper result = (Looper)e.value; return result; } } //第三步 创建一个Looper return setInitialValue(); } ThreadLocalMap getMap(Thread t) { //第二步: 返回的是当前线程里的一个成员变量ThreadLocalMap threadLocals return t.threadLocals; } private Looper setInitialValue() { //第四步:通过initialValue()api得到了一个Looper 而initialValue()方法直接return 了一个null //所这在没有做调用其它api的情况下ThreadLocal.get()方法获取的值为null Looper value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else //第五步: 创建ThreadLocalMap ,将Thread 里的成员变量threadLocals 附值 //threadLocals = new ThreadLocalMap(this, firstValue);this为ThreadLoca, firstValue第一次为null //这个时候当前线程的threadLocals就不为null了 createMap(t, value); return value; } protected Looper initialValue() { return null; } void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); } } class Thread implements Runnable { ThreadLocal.ThreadLocalMap threadLocals = null; } //再来分析Looper里是怎么将sThreadLocal里设置值的 public final class Looper { static final ThreadLocal sThreadLocal = new ThreadLocal (); private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("only one Looper may be created per thread"); } //第六步: 调用sThreadLocal.set方法将新创建的Looper给设置进去 sThreadLocal.set(new Looper(quitAllowed)); } //第九步:当set完值的时候再去get这就完全不一样了。 public static @Nullable Looper myLooper() { return sThreadLocal.get(); } public Looper get() { Thread t = Thread.currentThread(); //以当前线程为key去找值,获取的是当前线程的成员变量threadLocals,这个时候也不为null。且是每个Thread类独有的 ThreadLocalMap map = getMap(t); //这个时候map不为null了,已经有值了 if (map != null) { //第十步:当set完值的时候再去get这就完全不一样了。 //ThreadLocalMap.getEntry,获取缓存 ThreadLocalMap其实相当于一个这样的HashMap //ThreadLocalMap.Entry 是一个WeakReference > //ThreadLocalMap里有个成功变量Entry[] table他会保存很多Entry //每个ThreadLocalMap.Entry又执有了不同的ThreadLocal 和泛型T(Looper)类 ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") Looper result = (Looper)e.value; return result; } } //第三步 创建一个Looper return setInitialValue(); } } public class ThreadLocal { public void set(Looper value) { Thread t = Thread.currentThread(); //第七步: 通过getMap获取当前线程的ThreadLocalMap ,如果在set之前什么没有调用ThreadLocal里的get方法那么这个map就为null //如果在set之前调用了get方法,那么这个map就不为null ThreadLocalMap map = getMap(t); if (map != null) //第八步: 将传进来的Looper给设置进来了,key为ThreadLocal也主是Looper里的成功变量sThreadLocal valus为创建的Looper map.set(this, value); else //第五步: 创建ThreadLocalMap ,将Thread 里的成员变量threadLocals 附值 //threadLocals = new ThreadLocalMap(this, firstValue);this为ThreadLocal, firstValue这个时候为value 不为null了 //这个时候当前线程的threadLocals就不为null了 createMap(t, value); } }
1:每一个Thread都执有一个ThreadLocalMap变量threadLocals 他是通过ThreadLocal的createMap()方法创建
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
2:ThreadLocalMap是ThreadLocal的一个内部类,他相当于一个HashMap
3:而每一个Thread都执有一个ThreadLocalMap变量所以每一个线程里只要传入的ThreadLocal不变获取到的值也是唯一的。
4:ThreadLocalMap里有一个内部类 Entry
5:Entry这个类他会执行一个ThreadLocal和传进来的Object
6:ThreadLoca.get()先是获取本线程的一个ThreadLocalMap,然后通过ThreadLocalMap的getEntry方法找到值
示例
public class ThreadLocalTest {
public static void main (String [] args) {
ThreadLocal threadLocal = new ThreadLocal() {
@Override
protected Integer initialValue() {
return 1;
}
};
new Thread(() -> {
Integer integer = threadLocal.get();
threadLocal.set(integer + 4);
System.out.println("threadLocal1111: " + threadLocal.get());
}).start();
new Thread(() -> {
System.out.println("threadLocal22222: " + threadLocal.get());
}).start();
new Thread(() -> {
System.out.println("threadLocal33333 before: " + threadLocal.get());
threadLocal.set(9);
System.out.println("threadLocal33333 after :" + threadLocal.get());
}).start();
}
日志输出如下:
System.out: threadLocal1111: 5
System.out: threadLocal22222: 1
System.out: threadLocal33333 before: 1
System.out: threadLocal33333 after :9
每一个线程 threadLocal都是不同的,他们也是隔离的,在一个线程设置值对其它线程是没有影响的
}



