从源码来分析ThreadLocal、Message、Handler、Looper、MessageQueue
来源:互联网 发布:吃鸡要加装什么软件吗 编辑:程序博客网 时间:2024/05/16 17:42
ThreadLocal
ThreadLocal是一个负责存储数据的类,其原理是通过一个数组,存储key-value数据,key是线程,value是存储的数据。下面通过源码看一下。
看源码之前,先做个概述,这样看源码时思路更清晰。
1、ThreadLocal:负责存取数据的“工具类”,传入Thread作为参数,就能存取该线程对应的数据;
2、ThreadLocalMap:是ThreadLocal的内部类,这个是数据管理类,具体的存取操作也由这个类完成。它持有一个成员变量Entry[]数组,这个数组就是存放数据的。Thread类持有一个ThreadLocalMap成员变量,用于存放数据;
3、Entry:是ThreadLocalMap的内部类,是真正存放数据的key-value实体类;
看ThreadLocal存取数据的set、get方法:
public void set(T value) { // 获取当前Thread Thread t = Thread.currentThread(); // 获取当前Thread的ThreadLocalMap。 ThreadLocalMap map = getMap(t); if (map != null) // 把数据存入map中 map.set(this, value); else // 如果map没有初始化,就初始化map,并把数据存进去 createMap(t, value);}public T get() { // 获取当前Thread,以及当前线程对应的map Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { // 从map中取出数据。至于如何取、取的是哪条数据,具体的逻辑在ThreadLocalMap类中,本篇就不分析了 ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue();}
Message
看一下Message类的成员变量结构:
public final class Message implements Parcelable { public int what; public int arg1; public int arg2; public Object obj; // MessageQueue是一个链表结构存储Message,这个成员变量next,就是链表的下一个 private static final Object sPoolSync = new Object(); private static Message sPool; long when; // 每个Message都绑定在一个Handler上,这样Looper才知道要把这个Message交给谁处理 Handler target; ...... ......}
Handler
先看构造方法:
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()); } } // 初始化Looper。就是当前线程(Handler所在线程)的Looper mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } // 初始化MessageQueue。获取当前线程的MessageQueue mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
再看发送消息,所有的重载的sendMessage相关方法,最终都会调用sendMessageAtTime()方法:
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } // 调用了enqueueMessage() return enqueueMessage(queue, msg, uptimeMillis);}private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { // 给Message的target成员变量赋值,this就是Handler自身 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } // 调用MessageQueue的enqueueMessage()方法,把Message插入单链表中 return queue.enqueueMessage(msg, uptimeMillis);}
处理消息就没什么好讲的了,就是一个空方法,我们实现。Looper会取到消息中绑定的Handler,调用该Handler的dispatchMessage()方法,dispatchMessage()方法又会调用handMessage()方法。
Lopper
先看一下Looper的结构:
public final class Looper { final MessageQueue mQueue; final Thread mThread; // 通过ThreadLocal存放所有线程的Looper static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); // 主线程对应的Looper private static Looper sMainLooper; // guarded by Looper.class // 私有的构造方法 private Looper(boolean quitAllowed) { // new出当前线程对应的MessageQueue mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } // 我们只能通过prepare方法初始化Lopper public static void prepare() { prepare(true); } // new一个Looper,存入sThreadLocal中 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 public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } }}
再看一下Looper.loop()方法:
public static void loop() { // myLooper()方法就是获取到当前线程对应的Looper final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); // 一个死循环,不停地从MessageQueue中取出消息,并进行处理 for (;;) { // 从MessageQueue中取出消息 Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. // 如果返回的消息为null,就退出循环。 // 只有调用MeesageQueue的quit方法,才会返回null。没有消息时会在queue.next()中阻塞,不会返回null return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { // 调用Message绑定的Handler的dispatchMessage()方法 msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); }}
Android是一个消息驱动的系统,Activity创建,发送一个消息;屏幕有用户触摸,发送一个消息;用户按了返回键,发送一个消息。。。。如此反复循环。
ANR真正的意思是:处理某个消息超过了给定时间,或下一条消息到了时间迟迟无法顺利处理。所以,在主线程中处理耗时任务会导致ANR,而主线程Looper阻塞并不会造成ANR。
MessageQueue
MessageQueue翻译叫“消息队列”,实际上是一个单链表结构,它只持有一个Message对象,通过Message.next这样的方式,维护着一条消息链。
MessageQueue的主要作用就是插入消息、读取消息,对应的是enqueueMessage()/next()方法,先看插入消息:
boolean enqueueMessage(Message msg, long when) { if (msg.target == null) { throw new IllegalArgumentException("Message must have a target."); } if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) { if (mQuitting) { IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w(TAG, e.getMessage(), e); msg.recycle(); return false; } msg.markInUse(); msg.when = when; // mMessages可以认为是当前消息链中的“正在执行的消息”。我们把它描述为“标尺” Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < p.when) { // 如果“标尺”为null、或新来的消息需要立刻执行,就把新来的消息设置为“标尺”,原来的“标尺”设置为next msg.next = p; mMessages = msg; needWake = mBlocked; } else { needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; // 通过死循环,让消息队列中的所有消息依次首尾相连,直到next为null、或when比较靠后,就跳出循环 for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; } } // 消息队列首尾相连完成后,把新来的消息放入倒数第二个,最后一个为null或when比较靠后的消息 msg.next = p; // invariant: p == prev.next prev.next = msg; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { // 唤醒next()方法 nativeWake(mPtr); } }
再看读取消息:
Message next() { // Return here if the message loop has already quit and been disposed. // This can happen if the application tries to restart a looper after quit // which is not supported. final long ptr = mPtr; if (ptr == 0) { return null; } int pendingIdleHandlerCount = -1; // -1 only during first iteration // 初始化“下一条消息等待时间” int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } // 这是一个c++写的方法,传入下一条消息需要等待的时间,程序就会“阻塞”在这里,到时间后,继续向下执行 // 这个方法内部的阻塞使用的Linux系统的管道流机制,只会在next()方法内部阻塞,并不会阻塞整个线程 nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { // Try to retrieve the next message. Return if found. final long now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages; // 如果message绑定的Handler为null,就跳过,执行下一条 if (msg != null && msg.target == null) { // Stalled by a barrier. Find the next asynchronous message in the queue. do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) { if (now < msg.when) { // Next message is not ready. Set a timeout to wake up when it is ready. // 如果还没到message的执行时间,就设置阻塞时间 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { // Got a message. mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; if (DEBUG) Log.v(TAG, "Returning message: " + msg); msg.markInUse(); //如果一切OK,就返回message。Looper中就会得到message,开始处理 return msg; } } else { // No more messages. // 如果没有消息,就设置等待时间 nextPollTimeoutMillis = -1; } // Process the quit message now that all pending messages have been handled. // 如果调用了quit()方法,就返回null,Looper中获取的消息会null,就会退出循环 if (mQuitting) { dispose(); return null; } // If first time idle, then get the number of idlers to run. // Idle handles only run if the queue is empty or if the first message // in the queue (possibly a barrier) is due to be handled in the future. if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) { pendingIdleHandlerCount = mIdleHandlers.size(); } if (pendingIdleHandlerCount <= 0) { // No idle handlers to run. Loop and wait some more. mBlocked = true; continue; } if (mPendingIdleHandlers == null) { mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)]; } mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers); } // Run the idle handlers. // We only ever reach this code block during the first iteration. for (int i = 0; i < pendingIdleHandlerCount; i++) { final IdleHandler idler = mPendingIdleHandlers[i]; mPendingIdleHandlers[i] = null; // release the reference to the handler boolean keep = false; try { keep = idler.queueIdle(); } catch (Throwable t) { Log.wtf(TAG, "IdleHandler threw exception", t); } if (!keep) { synchronized (this) { mIdleHandlers.remove(idler); } } } // Reset the idle handler count to 0 so we do not run them again. pendingIdleHandlerCount = 0; // While calling an idle handler, a new message could have been delivered // so go back and look again for a pending message without waiting. nextPollTimeoutMillis = 0; }}
- 从源码来分析ThreadLocal、Message、Handler、Looper、MessageQueue
- Handler源码分析,Handler,Looper,Message,MessageQueue
- Handler、Looper、ThreadLocal、MessageQueue、Message
- (Handler+Message+Looper+MessageQueue)源码分析
- Handler,MessageQueue,Message,Looper源码分析
- android Handler Message MessageQueue Looper ThreadLocal源码解读
- 关于Looper,Handler,Message, MessageQueue,ThreadLocal的一些分析
- 从源码的角度解析Handler、Looper、Message和MessageQueue
- 从源码中分析Handler, Looper, Message, MessageQueue之间的关系
- 【安卓笔记】Handler,Looper,MessageQueue,Message源码分析
- Handler、Message、MessageQueue、Looper关系及源码分析
- Android 消息机制 - Handler, Looper, Message, MessageQueue 的源码分析
- Looper、Message、MessageQueue、Handler异步消息处理机制源码分析
- Android Handler、Looper、MessageQueue以及Message源码分析
- Handler、Looper、MessageQueue源码分析
- 源码浅析: Message/Handler/MessageQueue/Looper
- 源码浅析: Message/Handler/MessageQueue/Looper
- Android源码浅析: Message/Handler/MessageQueue/Looper
- 运算符、表达式
- appium三种等待元素的方法
- eight(hdu-1043)(待修正)
- ie浏览器下载rar文件,变成do文件
- Why do I keep getting 'SVN: Working Copy XXXX locked; try performing 'cleanup'?
- 从源码来分析ThreadLocal、Message、Handler、Looper、MessageQueue
- 算法导论 16-1.1活动选择问题 动态规划解
- 自定义一个背景可以滚动的tab栏
- freeMarker简单小总结
- python处理json
- 后台如何拼接easyUI tree格式的 json数据 构建动态树
- 相似性︱python+opencv实现pHash算法+hamming距离(simhash)(三)
- 无题
- poj 1178 Camelot(floyed+动规)