从源码来分析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;    }}
0 0