源码分析ThreadLocal在Handler中的作用
来源:互联网 发布:易到打车软件 编辑:程序博客网 时间:2024/05/16 19:38
源码分析ThreadLocal在Handler中怎样保证多线程并发时数据的访问安全
先来看一下Handler在new对象时所调用的构造方法:
public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
大家应该都清楚,handler如果要发挥作用,那么looper是必不可少的,所以在handler创建时,就会通过Looper的静态方法来创建一个looer来和hander一起工作。那么继续看这个Looper.myLooper()的静态方法内部的实现:
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */public static @Nullable Looper myLooper() { return sThreadLocal.get();}
可以看到他返回的是一个sThreadLocal.get()方法,OK,下面是这个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;}
这个源码应该比较简单啊,就是通过获取到当前线程的对象,来从一个map中去拿value,然后给他返回。这一块比较好理解,那么就有一个问题出来了,这个存储数据的map是什么时候添加了数据的呢?
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed));}
这段代码不知道大家有没有看过,Looper.prepare()方法不用我说大家应该都懂它的重要性,不管是主线程中系统底层自动去运行,还是子线程中我们去手动添加运行,反正在线程中使用handler,这个方法都是前提条件,这个大家应该明白的。那么很简单的就可以看出来,这个代码块仅仅是去给ThreadLocal给set了一个Looper对象。我们继续看
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }这里大家应该一目了然,是不是?通过获取Looper.prepare()方法执行的当前线程,来存储一个Looper对象,这样就使得Handler在new的时候能够获取到的就是关联了当前线程的一个looper。而且,因为使用的是map存储,所以只会存在一个当前线程的value,后面会把前面覆盖,就这么简单就实现了一个Looper、ThreadLocal以及Handler之间的关联。并且应该明白了如果你在子线程中使用Handler时的写法为什么会是下面这样了:* class LooperThread extends Thread { * public Handler mHandler; * * public void run() { * Looper.prepare(); * * mHandler = new Handler() { * public void handleMessage(Message msg) { * // process incoming messages here * } * }; * * Looper.loop(); * } * }通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,这样ThreadLocal就使得各线程能够保持各自独立的一个对象,而不会发生数据错乱的情况。
阅读全文
1 0
- 源码分析ThreadLocal在Handler中的作用
- ThreadLocal在spring框架中的作用
- ThreadLocal在spring框架中的作用
- ThreadLocal在spring框架中的作用
- ThreadLocal在spring框架中的作用
- 从源码来分析ThreadLocal、Message、Handler、Looper、MessageQueue
- Handler源码解析基于ThreadLocal来进行分析
- Handler作用及部分源码分析
- Hadoop源码分析17:IPC中的ThreadLocal
- ThreadLocal源码分析
- Threadlocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析解密
- ThreadLocal源码分析
- java-----ThreadLocal源码分析
- ThreadLocal源码分析
- selenium截取当前窗口,并保存为图片
- POJ3486 线段树
- 跳跃游戏二
- Tensorflow_Main parameters definition
- java环境配置
- 源码分析ThreadLocal在Handler中的作用
- module_t说明
- MySQL提示access denied for ''@'localhost'解决方案
- java自动补全如何取消空格确认
- xcode 常用快捷方式
- POJ2492 并查集
- 淘淘商城系列——分布式文件系统FastDFS
- T-SQL:用字符*显示一个三角形
- 一、简单工厂模式