前置:一个线程一个looper,1个looper一个messageQueue,一个messageQueue对应多个Message;一个messageQueue可以对应多个handler(一般消息队列中Looper是一个无限循环的操作,但是当队列中没有消息时,会阻塞沉睡,等待有消息时被唤醒)
一:messageQueue:它是一个单项的链表,方便插入,删除,里面存了很多个message,每个message都相当于一个链表上的点,通过Message中的next指向下一个消息,
不管是通过sendMessage还是postMesssage进行发送消息,它底层都是通过enqueueMessage(MessageQueue queue,Message,longuptimeMillin)方法中,插入队头,唤醒Looper,
二:从消息源码可以看出,它是通过一个for循环遍历是否有消息,并且会有个默认时间,第一次为0所以往下执行看是否有消息,没有消息就更改时间戳,让for循环处于阻塞状态,但是这种阻塞并不是销毁
后面还能唤醒,而延迟加载也是这个意思,设置一个时间,当经过这么长时间后,唤醒从新遍历是否有消息。
三:ThreadLocal
ThreadLocal提供了线程独有的局部变量存储的能力,可以整个线程存活的过程中随时随地的取用
1. 但是ThreadLocal仅仅是简化了存取工作,并不具备线程安全,比如开启多个线程操作它,会发现并不具备线程安全
2.它的数据类型,每一个线程对应一个ThreadLocalThreadMap对象,本质是一个数组实现的散列map
3.每个元素都是Entry对象,key=threadLocal,value为任意值
public T get() {
Thread t = Thread.currentThread();//当前的线程
ThreadLocalMap map = getMap(t);通过当前的线程来获取ThreadLocalMap
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);通过线程ThreadLocalMap 来获取队列Entry
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
1.通过查看Handler的源码可以清晰的看到,在Handler的构造方法中,直接通过Looper.myLooper来获取到了轮训器,从这方法我们也不难看出消息队列也是在这里获取到的mLooper.mQueue
public Handler(@Nullable 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 " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
2.继续往下查找可以发现Looper.myLooper是直接通过ThreadLocal来获取Looper的实例的,所以可以看出ThreadLocal的基本作用
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}