Android 线程间通信 – Java 层

源码基于 Android S AOSP,源码在线查看地址: cs.android.com/android/pla…

线程间通信在 Android 系统中应用十分广接口英文泛,本文是一个系列文章,主要梳理了Android Java层的线程间通信机制-Handler。

  • Android 线程间通信 – Java 层
  • Android 线程间通信 – Java 层 – MessagePool
  • Android 线程间通信 – Native 层

一个 Java 层简单的 H变量andler 示appearance例如下:

public void egHandler() {
    Looper.prepare();
    Looper.loop();
    Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            // TODO; 处理 Event
        }
    };
    new Thread() {
        @Override
        public void run() {
            Message msg = new Message();
            msg.what = 0;
            handler.sendMessage(msg);
        }
    }.start();
}

Java 层变量名的线程通信主要涉及到了Handler、MessageQueue、Message、Looper。

主线程创建的时候默认会执行Looper.pr源码网站epare()、Looper.线程池loop()方法,即默认会创建Looper

L变量名的命名规则ooper

源码路径frameworks/base/源码编辑器手机版下载core/java/android/os/Looper.java

Looper.prepare

public static void prepare() {
    // 调用Looper.prepare
    prepare(true);
}
private static void prepare(boolean quitAllowed) { // 默认传入 true, 允许中断
    // 从ThreadLocal中尝试拿出Looper对象
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    // ThreadLocal中没有Looper对象则进行创建
    sThreadLocal.set(new Looper(quitAllowed));
}

Looper.Looper

private Looper(boolean quitAllowed) {
    // 搞出来一个MessageQueue
    mQueue = new MessageQueue(quitAllowed);
    // 用一个变量保存当前线程(对应上面的示例也就是主线程)
    mThread = Thread.currentThread();
}

MessageQueue.MessageQueue

MessageQueue(boolean quitAllowed) {
    // 接收Looper传进的参数,默认允许中断
    mQuitAllowed = quitAllowed;
    // 初始化native方法,下一篇文章会说到
    mPtr = nativeInit();
}

Looper.loop

@SuppressWarnings("AndroidFrameworkBinderIdentity")
public static void loop() {
    // 从当前线程拿到 looper 对象
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    if (me.mInLoop) {
        Slog.w(TAG, "Loop again would have the queued messages be executed"
               + " before this one completed.");
    }
    // 标识 Looper 开始 loop
    me.mInLoop = true;
    // 清空远程调用端的pid和uid,使用本地进程的pid和uid代替
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();
    // Allow overriding a threshold with a system prop. e.g.
    // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
    final int thresholdOverride =
        SystemProperties.getInt("log.looper."
                                + Process.myUid() + "."
                                + Thread.currentThread().getName()
                                + ".slow", 0);
    me.mSlowDeliveryDetected = false;
    // 无线循环,调用loopOnce
    for (;;) {
        if (!loopOnce(me, ident, thresholdOverride)) {
            return;
        }
    }
}

Looper.myLooper

public static @Nullable Looper myLooper() {
    // 从当前线程中拿出 Looper 对象
    return sThreadLocal.get();
}

Loo线程是什么意思per.loopOnce

@SuppressWarnings("AndroidFrameworkBinderIdentity")
private static boolean loopOnce(final Looper me,
                                final long ident, final int thresholdOverride) {
    Message msg = me.mQueue.next(); // 从MessageQueue中取出Message,当MessageQueue中没有消息时,此处会阻塞
    // ......
    // Make sure the observer won't change while processing a transaction.
    final Observer observer = sObserver;
	// ......
    Object token = null;
    if (observer != null) {
        // 当注册了观察者时,调用观察者messageDispatchStarting方法
        token = observer.messageDispatchStarting();
    }
    long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
    try {
        // 调用消息的dispatchMessage方法,默认为Handler.dispatchMessage方法
        msg.target.dispatchMessage(msg);
        if (observer != null) {
            // 调用观察者 messageDispatched方法
            observer.messageDispatched(token, msg);
        }
        dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
    } catch (Exception exception) {
        if (observer != null) {
            observer.dispatchingThrewException(token, msg, exception);
        }
        throw exception;
    } finally {
        ThreadLocalWorkSource.restore(origWorkSource);
        if (traceTag != 0) {
            Trace.traceEnd(traceTag);
        }
    }
    // ......
	// 回收消息
    msg.recycleUnchecked();
    return true;
}

Looper.java中还有一些不常用的方法线程和进程的区别是什么

Looper.线程数越多越好吗myLooper

public static @Nullable Looper myLooper() {
	return sThreadLocal.get();
}

Looper.myQueue

public static @NonNull MessageQueue myQueue() {
    return myLooper().mQueue;
}

Looper.isCurrentThread

public boolean isCurrentThread() {
    return Thread.currentThread() == mThread;
}

Looper.quit

public void quit() {
    mQueue.quit(false);
}

Looper.quitSafely

public void quitSafely() {
    mQueue.quit(true);
}

Looper.getQueue

public @NonNull MessageQueue getQueue() {
    return mQueue;
}

Observer

在上线程安全面Looper.loopOnce中提到了Observ线程数越多越好吗er,该接口定义在Looper.java中,共三个方接口英文

public interface Observer {
    Object messageDispatchStarting();
    void messageDispatched(Object token, Message msg);
    void dispatchingThrewException(Object token, Message msg, Exception exception);
}

可以实现该接口,通过setObserver方法注册进去

public static void setObserver(@Nullable Observer observer) {
    sObserver = observer;
}

Handler

源码路径源码时代frameworks/base/core/java源码之家/android/os/Handler.java

Handler.Handle源码编辑器手机版下载r

@Deprecated
public Handler() {
	this(null, false);
}
@Deprecated
public Handler(@Nullable Callback callback) {
    this(callback, false);
}
// 指定Looper
public Handler(@NonNull Looper looper) {
    this(looper, null, false);
}
// 指定Looper和Callback
public Handler(@NonNull Looper looper, @Nullable Callback callback) {
    this(looper, callback, false);
}
public Handler(@Nullable Callback callback, boolean async) {
    // ......
    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;
}
@UnsupportedAppUsage // 此注解表示App无法使用该构造方法
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

Handle接口和抽象类的区别r.sendMessage

public final boolean sendMessage(@NonNull Message msg) {
    return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
// 定时发送消息,sendMessage代表now发送消息
public boolean sendMessageAtTime(@NonNull 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;
    }
    // 调用MessageQueue方法,将Message加入到MessageQueue中
    return enqueueMessage(queue, msg, uptimeMillis);
}

还有另外一种发送消息的方法,且消息中带有Callback

Handler.post

public final boolean post(@NonNull Runnable r) {
    return  sendMessageDelayed(getPostMessage(r), 0);
}
// token 即为message携带的数据
public final boolean postAtTime(
    @NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
    return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}

Hand源码中的图片ler.getPosrMessage

private static Message getPostMessage(Runnable r) {
    // 从消息池中取出一个空白消息
    Message m = Message.obtain();
    // 给message设置callback
    m.callback = r;
    return m;
}
@UnsupportedAppUsage
private static Message getPostMessage(Runnable r, Object token) {
    Message m = Message.obtain();
    // 给message设置obj数据
    m.obj = token;
    m.callback = r;
    return m;
}

Handler.obtainMessage

// 从消息池中取出一个Message使用
public final Message obtainMessage()
{
    return Message.obtain(this);
}

Handler.dispatchMessage

// Looper.loopOnce中调用过来的,处理消息
public void dispatchMessage(@NonNull Message msg) {
    if (msg.callback != null) {
        // message有callback,直接走callback
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            // handler有callback,走callback,callback内返回true则直接return,不会执行handlerMessage方法
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

Handler.han变量分为什么变量和什么变量dleMe接口英文ssage

// 由Handler的子类实现,用来处理消息,不实现则不会做任何事,空函数
public void handleMessage(@NonNull Message msg) {
}

MessageQueue

源码路径:frameworks/base/core/java/android/os/MessageQueue.java

MessageQueue.enqueueMessage

    boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        synchronized (this) {
            if (msg.isInUse()) {
                // inUse 抛出异常
                throw new IllegalStateException(msg + " This message is already in use.");
            }
            if (mQuitting) {
                // 表示正在执行结束流程
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                // 回收掉此message,加入message池
                msg.recycle();
                return false;
            }
            msg.markInUse();
            msg.when = when;
            // mMessages 为Message链表,MessageQueue的主要数据结构
            Message p = mMessages;
            // 唤醒标识
            boolean needWake;
            // 三种条件:
            // 1. MessageQueue中无Message
            // 2. 消息分发的时间为now
            // 3. 新消息的发送时间小于链表头部消息的时间
            if (p == null || when == 0 || when < p.when) {
                // 放在链表头
                msg.next = p;
                mMessages = msg;
                // 需要唤醒MessageQueue.next()
                needWake = mBlocked;
            } else {
                // 链表头不为空,则需要将Message插入到链表中
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
            // 需要唤醒则调用native方法唤醒MessageQueue.next
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

enqueueM线程撕裂者essa接口卡ge中,新me源码编辑器手机版下载ssage的位置有两种可能:

  • 链表头为空、当前message的发送时间变量类型有哪些为0、message的发送时间小于链表头的message发送时间,满足任意一项则将message插入到链表头源码时代
  • 循环遍历链表,找到链表节点中m变量之间的关系essage的时间大于新message时间的位置 ,将新message插入该位置,找不到则插入到链表尾部

MessageQueue.next

@UnsupportedAppUsage
Message next() {
    // 此处保存的是native层NativeMessageQueue指针
    final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }
    int pendingIdleHandlerCount = -1; 
    int nextPollTimeoutMillis = 0;
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }
        // 此处调用native方法,会阻塞,第一次调用会一直阻塞(pendingIdleHandlerCount = -1代表一直阻塞)
        nativePollOnce(ptr, nextPollTimeoutMillis);
        // 阻塞超时、MessageQueue中有新消息、发生ERROR 时调用以下方法
        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            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) {
                    // MessageQueue中链表头结点的发送时间大于now,需要等待
                    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;
                    }
                    // 取出MessageQueue链表的头节点,给Looper.loopOnce使用
                    msg.next = null;
                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                    msg.markInUse();
                    return msg;
                }
            } else {
                // No more messages.
                nextPollTimeoutMillis = -1;
            }
            // Process the quit message now that all pending messages have been handled.
            if (mQuitting) {
                dispose();
                return null;
            }
            // 如果MessageQueue中无Message或者链表头Message还没都发送的时间,从mIdleHandlers中获取到idleHandler个数
            // mIdleHandlers通过addIdleHandler添加
            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);
        }
        // 从mPendingIdleHandlers取出IdelHandler执行
        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 {
                // queueIdle返回false,则将当前IdelHandler从mIdleHandlers中彻底移除掉
                keep = idler.queueIdle();
            } catch (Throwable t) {
                Log.wtf(TAG, "IdleHandler threw exception", t);
            }
            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }
        // 将pendingIdleHandlerCount置空
        pendingIdleHandlerCount = 0;
        // 在执行IdelHander的时候,可能MessageQueue中可能已经有消息到来或者原有消息分发时间已到,将等待时间变为0
        nextPollTimeoutMillis = 0;
    }
}

当MessageQueue中有消息时,会将消息返回Looper.loopOnce,如没有消息或分发时间未到,则会执行IdelHandler中方法(IdelHandler需要Api调用者通源码过addIdleHander手动add),不会浪费等待源码时代培训怎么样的时间。

MessageQueue.addIdleHandler

public void addIdleHandler(@NonNull IdleHandler handler) {
    if (handler == null) {
        throw new NullPointerException("Can't add a null IdleHandler");
    }
    synchronized (this) {
        mIdleHandlers.add(handler);
    }
}

MessageQueue.removeMessages

void removeMessages(Handler h, int what, Object object) {
    if (h == null) {
        return;
    }
    synchronized (this) {
        // Message链表头
        Message p = mMessages;
        // Remove all messages at front.
        while (p != null && p.target == h && p.what == what
               && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }
        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && n.what == what
                    && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

该函数的作用是从MessageQueue中清除条件appointment满足msg.target = h &&变量类型有哪些amp; msg.what = what &&源码之家 (msg.obj == null || msg.ob变量与函数j = object)的message。

清除的方式也很特别,分为两段进行

  • 找到和给定条件相等的mesappearancesage
    • 找到则清除掉该msg,并让链表头和指向该节点的next
    • 找不到则退出循环
  • 源码编辑器下载上一个循环的位置开始,接着变量的英文遍历链表
    • 找到和给定条件相等的msg,清除掉msg
    • 找不到接着遍历,直到 p == null

Messa线程和进程的区别是什么geQueue.quit

void quit(boolean safe) {
    if (!mQuitAllowed) {
        // mQuitAllowed是构造方法传进来的,为true代表可以终止,为false在此方法内会抛出异常
        throw new IllegalStateException("Main thread not allowed to quit.");
    }
    synchronized (this) {
        if (mQuitting) {
            // 正在 quit,直接 return
            return;
        }
        mQuitting = true;
        if (safe) {
            removeAllFutureMessagesLocked();
        } else {
            removeAllMessagesLocked();
        }
        // We can assume mPtr != 0 because mQuitting was previously false.
        nativeWake(mPtr);
    }
}

quit方法主要线程是什么意思作用是停掉MessageQueue,释放掉MessageQueue中的节点,而释放掉哪些节点是通过参数接口文档safe进行控制的。

当safe为tru线程安全e时,调变量类型有哪些用removeAllFutureMessagesLocked方法,该方法变量内部会判断链表头节点源码之家msg的when

  • 当msg.whe接口是什么n > now时,证明链表中的所有节点都没有进行消息分发,可以全部释放
  • 当msg.when < now时,变量是什么意思需要遍历链表,找到msg.when > now的节点,从该节点开始进行释放,该节点之前的节点不可以释放,可能该节点之前的节点已经被分发出去了

当safe为false时,调用removeapproachAllMessagesLocked方法,暴力释放掉MessageQueue的所有节点

Message源码之家Queue.removeAllMessag变量名esLocked

private void removeAllMessagesLocked() {
    Message p = mMessages;
    while (p != null) {
        Message n = p.next;
        p.recycleUnchecked();
        p = n;
    }
    mMessages = null;
}

从链表中移除掉所有message,并且将链表头mMessages置为 null

MessageQueuappeare.removeAllFutureMess变量agesLocked

private void removeAllFutureMessagesLocked() {
    // 获取当前时间
    final long now = SystemClock.uptimeMillis();
    // 拿到链表头
    Message p = mMessages;
    if (p != null) {
        if (p.when > now) {
            // 链表头的msg发送时间大于当前时间,那链表中所有节点msg的发送时间也一定大于now,具体可以看enqueueMessage方法的实现
            // 暴力移除全部节点
            removeAllMessagesLocked();
        } else {
            Message n;
            // 遍历链表,找到msg.when > now的节点
            for (;;) {
                n = p.next;
                if (n == null) {
                    return;
                }
                if (n.when > now) {
                    break;
                }
                p = n;
            }
            // 断开节点
            p.next = null;
            // 回收掉链表剩余节点
            do {
                p = n;
                n = p.next;
                // 回收节点
                p.recycleUnchecked();
            } while (n != null);
        }
    }
}

Message

源码路径:frameworks/base/core/ja变量是什么意思va/android/os/Message.java

Filedapple苹果官网

字段 含义
what 可以看做消息的类型,以此字段标识消息
arg1 参数1
arg2 参数2
obj 消息携带的数据
whe源码编辑器手机版下载n 消息送给looper的时间
flag 标识当前Messag源码编辑器手机版下载e的状态,目前有FLAG_IN_USE、FLAG_ASYNCHRONOUS、appearFLAGS_TO_CLEAR_ON_COPY_FROM三种状态
next接口英文 Messapple苹果官网agePo线程数越多越好吗ol中链表节点链接指针

调用栈

-------------------------------------------- 向 MessageQueue 发送消息 -----------------------------------------------------
frameworks/base/core/java/android/os/Handler.java
    | ---> public final boolean sendMessage(@NonNull Message msg)
        | ---> return sendMessageDelayed(msg, 0);
            | ---> return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
                | ---> return enqueueMessage(queue, msg, uptimeMillis);
                    | ---> msg.target = this; // 将target指向当前 handler
                    | ---> return queue.enqueueMessage(msg, uptimeMillis);
frameworks/base/core/java/android/os/MessageQueue.java
                        | ---> msg.markInUse();
                        | ---> msg.when = when;
                        | ---> Message p = mMessages; // 拿到链表头
                        | ---> if (p == null || when == 0 || when < p.when) // 插在链表头部
                            | ---> msg.next = p;
                            | ---> mMessages = msg;
                            | ---> needWake = mBlocked;
                        | ---> else
                            | ---> for (;;) // 遍历链表,在链表中找到msg合适的插入位置
                            | ---> msg.next = p;
                            | ---> prev.next = msg; // 插入
                        | ---> nativeWake(mPtr); // if (needWake) 唤醒等待message的next()方法
------------------------------------------ Looper 循环从 MessageQueue 中拿到消息并处理 --------------------------------------
frameworks/base/core/java/android/os/Looper.java
    | ---> public static void loop()
        | ---> final Looper me = myLooper();
        | ---> for (;;)
            | ---> if (!loopOnce(me, ident, thresholdOverride)) // return;
                | ---> Message msg = me.mQueue.next(); // 从MessageQueue中拿到message,此处可能会阻塞
frameworks/base/core/java/android/os/MessageQueue.java
                    | ---> for (;;)
                        | ---> nativePollOnce(ptr, nextPollTimeoutMillis); // 可能会阻塞,需要nativeWake唤醒
                        | ---> Message msg = mMessages;
                        | ---> if (msg != null && msg.target == null)
                            | ---> while (msg != null && !msg.isAsynchronous());
                                | ---> prevMsg = msg;
                                | ---> msg = msg.next;
                        | ---> if (msg != null)
                            | ---> if (now < msg.when)
                                | ---> nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); // 计算需要等待的时间
                            | ---> else
                                | ---> prevMsg.next = msg.next; // if (prevMsg != null)
                                | ---> mMessages = msg.next; // else
                                | ---> msg.next = null;
                                | ---> msg.markInUse();
                                | ---> return msg; // 返回链表头节点
frameworks/base/core/java/android/os/Looper.java
                | ---> msg.target.dispatchMessage(msg); // target 指向自实现的 handler
frameworks/base/core/java/android/os/Handler.java
                    | ---> if (msg.callback != null)
                        | ---> handleCallback(msg);
                            | ---> message.callback.run();
                    | ---> else
                        | ---> if (mCallback != null)
                            | ---> if (mCallback.handleMessage(msg))
                                | ---> return // 上面的mCallback.handleMessage方法如返回true,则不会执行Handler.handleMessage方法
                        | ---> handleMessage(msg);
frameworks/base/core/java/android/os/Looper.java
                | ---> msg.recycleUnchecked(); // 回收掉message,将该msg加入到message poll

发表评论

提供最优质的资源集合

立即查看 了解详情