ThreadLocal源码解读
来源:互联网 发布:免费无限php空间 编辑:程序博客网 时间:2024/05/20 05:52
在学习Handler消息机制中Looper源码时看到ThreadLocal这个类,发现它很强大并且很方便的实现了对各个线程中Looper的管理。这个类的源码只有600行。下面先上一个简单的例子:
public class ThreadLocalTest { static ThreadLocal<Integer> intLocals = new ThreadLocal<Integer>(){ protected Integer initialValue() { return 1; } }; public static void main(String[] args) { intLocals.set(669); new MyThread("A线程").start(); System.out.println(Thread.currentThread().getName() + "====" + intLocals.get()); } static class MyThread extends Thread { public MyThread(String name){ super(name); } @Override public void run() { System.out.println(Thread.currentThread().getName() + "====" + intLocals.get()); } }}
这段代码的运行结果:
main====669A线程====1
提出问题:用static关键字修饰的静态变量intLocals
没效果吗,A线程中的输出结果不应该是669吗?
下面带着这个疑问去源码中寻找答案:
ThreadLocal类中只有一个空参的构造方法,所以关键的代码只有initLocals.set(669)
和initLocals.get()
了。
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); } /** * @param t the current thread */ ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
从源码中可以看出在Thread中定义了一个ThreadLocalMap的引用,如果该引用的对象不为null就会通过ThreadLocalMap的引用来调用set方法。ThreadLocalMap是ThreadLocal的一个静态内部类,而在ThreadLocalMap中还定义的一个静态的Entry类。以ThreadLocal作为键、Object为值的数据结构;并将键存放到了WeakReference中,即线程中没有ThreadLocal的其他引用时就会自动回收。如果map为空就会执行createMap()方法创建一个ThreadLocalMap对象。
/** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } // 默认的数组大小为16,自定义的话必须为2的幂 private static final int INITIAL_CAPACITY = 16; private Entry[] table;
由此可见map.set(this, value)
只是将当前的intLocals对象作为键,669作为值存储到主线程中。
get方法源码:
/** * Returns the value in the current thread's copy of this * thread-local variable. If the variable has no value for the * current thread, it is first initialized to the value returned * by an invocation of the {@link #initialValue} method. * * @return the current thread's value of this thread-local */ public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
get()通过获取当前线程的ThreadLocalMap对象map,遍历map中数组拿到键为this(即当前ThreadLocal的引用)的Entry实体,从而返回对应的键;map为空时就返回初始化时的值。
看了上面的源码应该能够解答示例中的疑问了:ThreadLocal中set(value)方法将调用这个方法的对象作为键、value为值存储到当前线程中ThreadLocalMap中;而get()方法取出时是根据调用这个方法的ThreadLocal对象到当前线程的ThreadLocalMap中查找对应的值,为空时就返回初始值。也就是说ThreadLocal的get和set方法的操作对象其实都是执行这两个方法所在线程的ThreadLocalMap对象,ThreadLocal只起到了一个键的作用。
ThreadLocal将对象的访问范围限制在线程中,并且当线程结束后ThreadLocal会被自动回收,也可以调用remove()(since 1.5)方法去掉线程中保存的变量。
另外,ThreadLocal不是为了解决线程间的同步问题,感觉恰恰相反,它是为了避免产生同步问题。既然如此,为什么又要整出ThreadLocal这么个东西,直接搞个局部变量不就好了吗?这个问题暂时不知道咋回答,以后再补上!!!
参考资料
Android7.0源码
彻底理解ThreadLocal
写个博客像挤牙膏样,逻辑混乱,感觉很多东西看了源码就那么回事,但是要用文字表达出来总是说不清楚,不知道怎么回事,希望过来人指点一二!
很烦躁…..
- ThreadLocal源码解读
- ThreadLocal源码解读
- 对ThreadLocal的源码解读
- ThreadLocal解读
- ThreadLocal解读
- android Handler Message MessageQueue Looper ThreadLocal源码解读
- ThreadLocal源码
- ThreadLocal 介绍,解读
- 源码解读
- ThreadLocal源码分析
- Threadlocal源码分析
- ThreadLocal源码解析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码解析
- ThreadLocal源码解析
- 源码浅析ThreadLocal类
- UESTC 929Post office(贪心)
- 一个免费的内网穿透工具-sunny-ngrok
- javascripts参考手册(含es6)
- hdu1863(水)
- 数据结构实验之图论二:基于邻接表的广度优先搜索遍历
- ThreadLocal源码解读
- 坑:在angular内使用DOM操作添加元素,被添加的元素不再具有使用ng指令的能力
- Jstorm 简介
- java中所有快捷键
- lightoj 1282 Leading and Trailing
- 深度学习-梯度下降
- Intel CMT & CAT & CDP 技术应用
- 【kubernetes/k8s源码分析】kube-scheduler 源码分析
- 幻梦