android Handler Message MessageQueue Looper ThreadLocal源码解读

xiaoxiao2021-02-28  72

android Handler Message MessageQueue Looper ThreadLocal源码解读

Looper不断获取MessageQueue中的一个Message,然后交给Hanlder处理。Message和Runnable可以一并压入MessageQueue中,形成一个集合

//Handler消息处理者, 1、处理Message public void handleMessage(Message msg); 2、将Message推入MessageQueue Message和Runnable对象,其结果实质都是将在Handler的队列中放入内容: message是放置信息、传递一些参数,Handler获取这些信息并将判度如何处理, Runnable则是直接给出处理的方法

Handler的消息发送(函数有很多中的,这里只是例取最简单的): sendMessage(Message msg)/post(Runnable r)->sendMessageDelayed()->sendMessageAtTime()->queue.enqueueMessage(),把Message推入MessageQueue队列 Handler类中持有MessageQueue和Looper成员变量

public class Handler { private static final boolean FIND_POTENTIAL_LEAKS = false; private static final String TAG = "Handler"; /** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. */ public interface Callback { public boolean handleMessage(Message msg); } /** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { // 3、需子类实现具体事务处理 } /** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } public Handler() { } public Handler(Callback callback) { } /** * Use the provided queue instead of the default one. */ public Handler(Looper looper) { // 传入Looper对象,以及Looper对象持有的MessageQueue消息队列,完成Handler的创建、初始化(从而Handler就实现了与Looper、MessageQueue的关联) mLooper = looper; // Handler的 mLooper 对象初始化 mQueue = looper.mQueue; // Handler的 mQueue 对象初始化 mCallback = null; } public Handler(Looper looper, Callback callback) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; } public String getMessageName(Message message) { if (message.callback != null) { return message.callback.getClass().getName(); } return "0x" + Integer.toHexString(message.what); } public final Message obtainMessage() //1、 Handler的消息获取函数obtainMessage(),它调用Message的静态方法obtain()产生消息,传入参数是handler本身 { return Message.obtain(this); } public final Message obtainMessage(int what) { return Message.obtain(this, what); } public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); } public final Message obtainMessage(int what, int arg1, int arg2) { return Message.obtain(this, what, arg1, arg2); } public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { return Message.obtain(this, what, arg1, arg2, obj); } public final boolean post(Runnable r) //2、Handler的消息发送函数:post()->sendMessageDelayed()->sendMessageAtTime()->queue.enqueueMessage(),把Message推入MessageQueue队列 { return sendMessageDelayed(getPostMessage(r), 0); } public final boolean postAtTime(Runnable r, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r), uptimeMillis); } public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); } public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } public final boolean postAtFrontOfQueue(Runnable r) { return sendMessageAtFrontOfQueue(getPostMessage(r)); } public final void removeCallbacks(Runnable r) { mQueue.removeMessages(this, r, null); } public final void removeCallbacks(Runnable r, Object token) { mQueue.removeMessages(this, r, token); } public final boolean sendMessage(Message msg) //2、Handler的消息发送函数:sendMessage()->sendMessageDelayed()->sendMessageAtTime()->queue.enqueueMessage(),把Message推入MessageQueue队列 { return sendMessageDelayed(msg, 0); } public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); } public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageAtTime(msg, uptimeMillis); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); // 入队函数 queue.enqueueMessage() } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } public final boolean sendMessageAtFrontOfQueue(Message msg) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, 0); // 入队函数 queue.enqueueMessage() } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } public final void removeMessages(int what) { mQueue.removeMessages(this, what, null, true); } public final void removeMessages(int what, Object object) { mQueue.removeMessages(this, what, object, true); } public final void removeCallbacksAndMessages(Object token) { mQueue.removeCallbacksAndMessages(this, token); } public final boolean hasMessages(int what) { return mQueue.removeMessages(this, what, null, false); } public final boolean hasMessages(int what, Object object) { return mQueue.removeMessages(this, what, object, false); } // if we can get rid of this method, the handler need not remember its loop // we could instead export a getMessageQueue() method... public final Looper getLooper() { return mLooper; } public final void dump(Printer pw, String prefix) { pw.println(prefix + this + " @ " + SystemClock.uptimeMillis()); if (mLooper == null) { pw.println(prefix + "looper uninitialized"); } else { mLooper.dump(pw, prefix + " "); } } @Override public String toString() { return "Handler (" + getClass().getName() + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}"; } final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } } private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { Handler.this.sendMessage(msg); } } private final Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } private final Message getPostMessage(Runnable r, Object token) { Message m = Message.obtain(); m.obj = token; m.callback = r; return m; } private final void handleCallback(Message message) { message.callback.run(); } final MessageQueue mQueue; // MessageQueue 成员变量 final Looper mLooper; // Looper 成员变量 final Callback mCallback; IMessenger mMessenger; }

//Message定义消息的描述和属性数据

public final class Message implements Parcelable { public int what; //消息标识 public int arg1; public int arg2; public Object obj; //obj是Object类型的任意对象 /** * Optional Messenger where replies to this message can be sent. The * semantics of exactly how this is used are up to the sender and * receiver. */ public Messenger replyTo; //replyTo是消息管理器 static final int FLAG_IN_USE = 1; static final int FLAGS_RESERVED = ~FLAG_IN_USE; static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAGS_RESERVED | FLAG_IN_USE; int flags; long when; Bundle data; Handler target; Runnable callback; // sometimes we store linked lists of these things Message next; private static final Object sPoolSync = new Object(); private static Message sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 10; public static Message obtain() { // 实际产生Message的静态函数 synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); } //以下的obtain(...)函数内部都是调用obtain()去真正产生一个Message public static Message obtain(Message orig) { } public static Message obtain(Handler h) { Message m = obtain(); m.target = h; return m; } public static Message obtain(Handler h, Runnable callback) { } public static Message obtain(Handler h, int what) { } public static Message obtain(Handler h, int what, Object obj) { } public static Message obtain(Handler h, int what, int arg1, int arg2) { } public static Message obtain(Handler h, int what, } ... }

//MessageQueue类,用来存放消息的消息队列,具有队列的入队、出队、移除操作 //MessageQueue作为线程的消息存储仓库,配合Handler, Looper一起完成一系列操作

public class MessageQueue { Message mMessages; private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>(); private IdleHandler[] mPendingIdleHandlers; private boolean mQuiting; boolean mQuitAllowed = true; // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout. private boolean mBlocked; @SuppressWarnings("unused") private int mPtr; // used by native code private native void nativeInit(); private native void nativeDestroy(); private native void nativePollOnce(int ptr, int timeoutMillis); private native void nativeWake(int ptr); ... MessageQueue() { nativeInit(); } @Override protected void finalize() throws Throwable { try { nativeDestroy(); } finally { super.finalize(); } } final Message next() { // 出队 int pendingIdleHandlerCount = -1; // -1 only during first iteration int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } nativePollOnce(mPtr, nextPollTimeoutMillis); synchronized (this) { // Try to retrieve the next message. Return if found. final long now = SystemClock.uptimeMillis(); final Message msg = mMessages; if (msg != null) { final long when = msg.when; if (now >= when) { mBlocked = false; mMessages = msg.next; msg.next = null; if (false) Log.v("MessageQueue", "Returning message: " + msg); msg.markInUse(); return msg; } else { nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE); } } else { nextPollTimeoutMillis = -1; } // If first time, then get the number of idlers to run. if (pendingIdleHandlerCount < 0) { 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("MessageQueue", "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; } } final boolean enqueueMessage(Message msg, long when) { // MessageQueue消息入队函数:将Message推入队列 if (msg.isInUse()) { // Message是否在使用 throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { // Message的持有者handler是否为null throw new RuntimeException("Main thread not allowed to quit"); } final boolean needWake; synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } msg.when = when; //Log.d("MessageQueue", "Enqueing: " + msg); Message p = mMessages; if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; needWake = mBlocked; // new head, might need to wake up } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; needWake = false; // still waiting on head, no need to wake up } } if (needWake) { nativeWake(mPtr); //通过内存指针 } return true; } final boolean removeMessages(Handler h, int what, Object object, boolean doRemove) { // 消息移除 } final void removeMessages(Handler h, Runnable r, Object object) { } final void removeCallbacksAndMessages(Handler h, Object object) { } }

//Looper持有一个MessageQueue

ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。 使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 从线程的角度看,目标变量就象是线程的本地变量。

public class ThreadLocal<T> { public ThreadLocal(); public T get(); protected T initialValue(); public void remove(); public void set(T); static class ThreadLocalMap { ... } }

void set(Object value)设置当前线程的线程局部变量的值。 public Object get()该方法返回当前线程所对应的线程局部变量。 public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作, 但它可以加快内存回收的速度。 protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法, 在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null

ThreadLocal用来解决对象共享访问: 1。每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,隔离了多个线程对数据的访问冲突,线程可以正确的访问到自己的对象。 2。将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap(用于存储每一个线程的变量副本,ThreadLocalMap中元素的键为线程对象,而值对应线程的变量副本)中, 然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦 3、ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new对象的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本

//1、通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值

private static ThreadLocal<Integer> idNum = new ThreadLocal<Integer>() { // 每个线程都能保持一个整型的idNum对象 public Integer initialValue() { return 0; } };

//2、获取下一个ID值

public int getIdNum() { idNum.set(idNum.get() + 1); return idNum.get(); } public class Looper { private static final String TAG = "Looper"; // sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); // ThreadLocal负责创建一个只针对当前线程的Looper及其它相关数据对象,其它线程无法访问 final MessageQueue mQueue; // 持有一个MessageQueue对象 final Thread mThread; // volatile boolean mRun; private Printer mLogging = null; private static Looper mMainLooper = null; // guarded by Looper.class /** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { // prepare() 之后调用loop(), 退出调用quit() if (sThreadLocal.get() != null) { //判断保证一个Thread只能有一个Looper实例 throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); // 初始化当前线程为一个Looper(new Looper()实例化一个Looper), 实现Looper绑定线程 } /** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(); setMainLooper(myLooper()); myLooper().mQueue.mQuitAllowed = false; } private synchronized static void setMainLooper(Looper looper) { mMainLooper = looper; } /** Returns the application's main looper, which lives in the main thread of the application. */ public synchronized static Looper getMainLooper() { return mMainLooper; } /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { //一是创建处理消息的环境;二是循环处理消息 Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } 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(); while (true) { Message msg = queue.next(); // might block 从MessageQueue中取出一个消息,可能会阻塞 if (msg != null) { //当前消息队列中没有Message if (msg.target == null) { //或者Message的持有者为null,则线程退出; // No target is a magic identifier for the quit message. return; } long wallStart = 0; long threadStart = 0; // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); wallStart = SystemClock.currentTimeMicro(); threadStart = SystemClock.currentThreadTimeMicro(); } msg.target.dispatchMessage(msg); // 调用handler进行消息分发 if (logging != null) { long wallTime = SystemClock.currentTimeMicro() - wallStart; long threadTime = SystemClock.currentThreadTimeMicro() - threadStart; logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); if (logging instanceof Profiler) { ((Profiler) logging).profile(msg, wallStart, wallTime, threadStart, threadTime); } } // 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.recycle(); } } } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); // 返回当前线程与之关联的Looper实例 } public void setMessageLogging(Printer printer) { mLogging = printer; } /** * Return the {@link MessageQueue} object associated with the current * thread. This must be called from a thread running a Looper, or a * NullPointerException will be thrown. */ public static MessageQueue myQueue() { // 返回与当前线程关联的消息队列 return myLooper().mQueue; } private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); } public void quit() { Message msg = Message.obtain(); // NOTE: By enqueueing directly into the message queue, the // message is left with a null target. This is how we know it is // a quit message. mQueue.enqueueMessage(msg, 0); } /** * Return the Thread associated with this Looper. */ public Thread getThread() { return mThread; } /** @hide */ public MessageQueue getQueue() { return mQueue; } ... }

一个Thread只对应一个Looper 一个Looper只对应一个MessageQueue 一个MessageQueue可有多个Message 一个Message只能指定一个Handler来处理

转载请注明原文地址: https://www.6miu.com/read-54420.html

最新回复(0)