android 分发消息函数,Android消息机制

前菜

介绍

Handler机制为Android提供给予开发者用于线程间切换,处理Java层消息与Native层消息的一种机制。

相关类

Java层

Thread

ThreadLocal

ThreadLocalMap

Looper

Message

MessageQueue

Handler

Native层

Looper

ALooper

NativeMessageQueue

Message

MessageHandler

WeakMessageHandler

基础知识介绍

1. ThreadLocal

源码链接

类关系

public class ThreadLocal {

static class ThreadLocalMap {

private static final int INITIAL_CAPACITY = 16;

private Entry[] table = new Entry[INITIAL_CAPACITY];

static class Entry extends WeakReference> {

Object value;

Entry(ThreadLocal> k, Object v) {

super(k);

value = v;

}

}

}

}

一般使用ThreadLocal例子,以Looper为例。

static final ThreadLocal sThreadLocal = new ThreadLocal();

...

sThreadLocal.set(new Looper(quitAllowed));

储存数据

public class ThreadLocal {

...

public void set(T value) {

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null)

map.set(this, value);

else

createMap(t, value);//第一次存储,该map一定为空

}

//从当前线程的 threadLocals 变量获取ThreadLocalMap对象

ThreadLocalMap getMap(Thread t) {

return t.threadLocals;

}

//创建ThreadLocalMap对象,并保存到当前线程的threadLocals变量中。

void createMap(Thread t, T firstValue) {

t.threadLocals = new ThreadLocalMap(this, firstValue);

}

}

public class Thread implements Runnable{

...

ThreadLocal.ThreadLocalMap threadLocals = null;

...

}

ThreadLocalMap结构

static class ThreadLocalMap{

...

ThreadLocalMap(ThreadLocal> firstKey, Object firstValue) {

table = new Entry[INITIAL_CAPACITY];

int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);

table[i] = new Entry(firstKey, firstValue);

size = 1;

setThreshold(INITIAL_CAPACITY);

}

private void set(ThreadLocal> key, Object value) {

Entry[] tab = table;

int len = tab.length;

int i = key.threadLocalHashCode & (len-1);

for (Entry e = tab[i];

e != null;

e = tab[i = nextIndex(i, len)]) {

ThreadLocal> k = e.get();

if (k == key) {

e.value = value;

return;

}

//如果ThreadLocal被回收了,则也进行Entry数组的回收工作

if (k == null) {

replaceStaleEntry(key, value, i);

return;

}

}

tab[i] = new Entry(key, value);

int sz = ++size;

if (!cleanSomeSlots(i, sz) && sz >= threshold)

rehash();

}

}

读取数据

public class ThreadLocal {

public T get() {

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null) {

ThreadLocalMap.Entry e = map.getEntry(this);

if (e != null) {

@SuppressWarnings("unchecked")

T result = (T)e.value;

return result;

}

}

//第一次获取,map为空,直接走初始化方法

return setInitialValue();

}

private T setInitialValue() {

T value = initialValue();

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null)

map.set(this, value);

else

createMap(t, value);

return value;

}

//如果之前没有保存过该ThreadLocal,则先存入一个null进入。

protected T initialValue() {

return null;

}

}

4253f551e877

image

结论

ThreadLocal 里面有一个静态内部类 ThreadLocalMap,ThreadLocalMap 有个静态类 Entry,Entry继承 WeakReference。

ThreadLocal 是一个工具类,主要负责从当前 Thread 中操作 ThreadLocalMap。

ThreadLocalMap 里面维护着一个 Entry 数组,每一个 Entry 对象都保存着一个以ThreadLocal 为key,Object 为value的结构。

Entry 里面的key被封装为弱引用,便于释放回收处理。

在同一个线程中,ThreadLocal对象与Object进行组合,同一个ThreadLocal对象,在Entry中只能保存一个值。

2. epoll 机制

epoll 是 Linux 提供的高效访问 I/O 的机制。

1.使用epoll前,需要先通过 epoll_create 函数创建一个epoll句柄。

// 创建能容纳10个fd相关信息的缓存。

int epollHandle = epoll_create( 10 );

2.得到epoll句柄后,通过epoll_ctl 把需要监听的文件句柄加入 epoll 句柄中。

// 先定义一个event

struct epoll_event listenEvent;

// 指定该句柄的可读事件

// EPOLLIN(句柄可读)

// EPOLLOUT(句柄可写)

// EPOLLERR(句柄错误)

// EPOLLUP(句柄断)

listenEvent.events = EPOLLIN;

// epoll_event 中有个联合体叫data,用来存储上下文数据。

data.fd = listenEvent;

3.EPOLL_CTL_ADD将监听fd和监听事件加入epoll句柄的等待队列中。

// EPOLL_CTL_DEL 将监听fd从epoll句柄中移除。

// EPOLL_CTL_MOD修改fd的监听事件。

epoll_ctl(epollHandle, Epoll_CTL_ADD ,listener, &listenEvent)

4调用epoll_wait用于等待事件。

struct epoll_event resultEvents[10];

......

int timeout = -1;

while(1){

int nfds == epoll_wait(epollHandle,resultEvents,10,timeout);

// nfds 大于0表示所监听的句柄上有事件发生。

// nfds 等于0表示等待超时。

// nfds 小于0表示等待过程中发生了错误。

//

if(nfds == -1){

//错误

}else if(nfds == 0){

//超时

}else{

//resultEvents 用于返回哪些发生了事件的信息。

struct epoll_event &event = resultEvents[i];

if(event & EPOLLIN){

//收到可读事件

......

}

......//其他处理

}

}

//添加监听

int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) ;

//处理监控请求

void Looper::pushResponse(int events, const Request& request) ;

正餐

Looper、MessageQueue、NativeMessageQueue创建过程

相关源码链接:

一般使用Looper,以ActivityThread为例。

public final class ActivityThread{

public static void main(String[] args) {

Looper.prepareMainLooper();

...

Looper.loop();

}

}

构建Looper对象

使用ThreadLocal工具保存到ThreadLocalMap中。

public final class Looper {

//ThreadLocal声明为静态对象,确保在同一个线程下,只有一个Looper对象存在。

static final ThreadLocal sThreadLocal = new ThreadLocal();

public static void prepareMainLooper() {

prepare(false);

synchronized (Looper.class) {

if (sMainLooper != null) {

throw new IllegalStateException("The main Looper has already been prepared.");

}

sMainLooper = myLooper();

}

}

//创建Looper对象,并将Looper对象保存到ThreadLocalMap中。

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));

}

//从ThreadLocalMap中获取Looper对象。

public static Looper myLooper() {

return sThreadLocal.get();

}

}

构建MessageQueue队列

public final class Looper {

final MessageQueue mQueue;

final Thread mThread;

...

private Looper(boolean quitAllowed) {

mQueue = new MessageQueue(quitAllowed);

mThread = Thread.currentThread();

}

}

public final class MessageQueue {

private final boolean mQuitAllowed;

private long mPtr;

MessageQueue(boolean quitAllowed) {

mQuitAllowed = quitAllowed;

//构造函数调用naitveInit,该函数由Native层实现。

//Native层的 NativeMessageQueue 对象引用指针。

mPtr = nativeInit();

}

}

构建Native层 NativeMessageQueue 对象

nativeInit 方法在 frameworks/base/core/jni/android_os_MessageQueue.cpp 定义实现。

class NativeMessageQueue : public MessageQueue, public LooperCallback {

static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {

NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();

if (!nativeMessageQueue) {

jniThrowRuntimeException(env, "Unable to allocate native queue");

return 0;

}

nativeMessageQueue->incStrong(env);

return reinterpret_cast(nativeMessageQueue);

}

NativeMessageQueue::NativeMessageQueue() :

mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {

//一个线程会有一个Looper循环来处理消息队列中的消息。

//获取保存在本地线程的存储空间的Looper对象

mLooper = Looper::getForThread();

if (mLooper == NULL) {

//如果第一次进来,则该线程没有设置本地存储,所以需要先创建一个Looper,然后后再将其保存到TLS中,

//这是很常见的一种以线程为单位的单利模式。

mLooper = new Looper(false);

Looper::setForThread(mLooper);

}

}

}

注册epoll机制

Looper::Looper(bool allowNonCallbacks)

: mAllowNonCallbacks(allowNonCallbacks),

mSendingMessage(false),

mPolling(false),

mEpollRebuildRequired(false),

mNextRequestSeq(0),

mResponseIndex(0),

mNextMessageUptime(LLONG_MAX) {

// Android 6.0 之前为 pipe, 6.0 之后为 eventfd

mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));

LOG_ALWAYS_FATAL_IF(mWakeEventFd.get() < 0, "Could not make wake event fd: %s", strerror(errno));

AutoMutex _l(mLock);

rebuildEpollLocked();

}

void Looper::rebuildEpollLocked() {

// 如果有新的epoll事件,则把原来的epoll事件关闭

if (mEpollFd >= 0) {

mEpollFd.reset();

}

// Allocate the new epoll instance and register the wake pipe.

// 创建一个epoll实例,并注册wake管道

mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));

LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));

struct epoll_event eventItem;

memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union

// 监听可读事件

eventItem.events = EPOLLIN;

// 监控的fd为唤醒事件fd

eventItem.data.fd = mWakeEventFd.get();

int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mWakeEventFd.get(), &eventItem);

LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance: %s",

strerror(errno));

// 如果请求队列中有数据,则还需要将请求中的事件注册到epoll实例中

for (size_t i = 0; i < mRequests.size(); i++) {

const Request& request = mRequests.valueAt(i);

struct epoll_event eventItem;

request.initEventItem(&eventItem);

// 注册请求中的事件到epoll实例中

int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);

if (epollResult < 0) {

ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",

request.fd, strerror(errno));

}

}

}

4253f551e877

image

Handler

相关源码链接:

构建Handler

public class Handler {

final Looper mLooper;

final MessageQueue mQueue;

public Handler() {

this(null, false);

}

public Handler(Callback callback) {

this(callback, false);

}

public Handler(Looper looper) {

this(looper, null, false);

}

...

public Handler(Looper looper,Callback callback) {

this(looper, callback, false);

}

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;

}

public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {

mLooper = looper;

mQueue = looper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

}

通过Handler发送Message

举个栗子

Handler mHandler = new Handler();

#1.1 发送空消息

mHandler.sendEmptyMessage(what);

#1.3 发送延时消息

mHandler.sendEmptyMessageDelayed(what, 0);

#2.1 发送Message对象

Message msg = Message.obtail();

msg.what = ...;

msg.obj = ...;

mHandler.sendMessage(msg);

#2.2 发送延时消息

mHandler.sendMessageDelayed(msg,1000);

#2.3 在指定时间发送消息

mHandler.sendMessageAtTime(msg,uptimeMillis);

#4. 发送Runnable消息

mHandler.post(Runnable r);

...

public class Handler {

//方式一

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 sendMessage(Message msg) {

return sendMessageDelayed(msg, 0);

}

//方式三

public final boolean post(@NonNull Runnable r) {

return sendMessageDelayed(getPostMessage(r), 0);

}

private static Message getPostMessage(Runnable r) {

Message m = Message.obtain();

m.callback = r;

return m;

}

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) {

MessageQueue queue = mQueue;

if (queue == null) {

RuntimeException e = new RuntimeException(

this + " sendMessageAtTime() called with no mQueue");

Log.w("Looper", e.getMessage(), e);

return false;

}

return enqueueMessage(queue, msg, uptimeMillis);

}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

//这里将当前Handler进行保存,主要为了后续分发到对应 Handler 的对象的 handleMessage 方法。

msg.target = this;

msg.workSourceUid = ThreadLocalWorkSource.getUid();

if (mAsynchronous) {

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg, uptimeMillis);

}

}

MessageQueue处理逻辑

Message结构

public final class Message implements Parcelable {

public int what;

public int arg1;

public int arg2;

public Object obj;

Handler target;//发送该Message的对象,用于回调

Runnable callback;

Message next;

public long when;//执行时间

...

}

MessageQueue 与 Message 关系图

MessageQueue里面维护的是Message链表。

4253f551e877

image

在Java层投递Message

public final class MessageQueue {

boolean enqueueMessage(Message msg, long when) {

......

boolean needWake;

synchronized (this) {

if (mQuitting) {

msg.recycle();

return false;

}

......

msg.when = when;

Message p = mMessages;

if (p == null || when == 0 || when < p.when) {

// 如果p为空,表明消息队列中没有消息,那么msg将是第一个消息,needwake需要根据mBlocked的

//情况考虑是否触发。

msg.next = p;

mMessages = msg;

needWake = mBlocked;

} else {

//如果p不为空,表明消息队列中还有剩余的消息,需要将新的msg添加到对应的位置。

needWake = mBlocked && p.target == null && msg.isAsynchronous();

Message prev;

for (;;) {

prev = p;

p = p.next;

//从消息队列中取出消息,判断该消息的触发时间,与要新添加的Message的时间对比。

//如果新添加的Message时间小于 当前消息队列中获取的Message的时间,则直接break。

if (p == null || when < p.when) {

break;

}

if (needWake && p.isAsynchronous()) {

needWake = false;

}

}

//将新添加的Message添加到该队列的指定位置。如下图所示

msg.next = p; // invariant: p == prev.next

prev.next = msg;

}

// We can assume mPtr != 0 because mQuitting is false.

//最后根据情况判断是否需要唤醒

if (needWake) {

// 调用nativeWake,以触发nativePollOnce函数结束等待。

nativeWake(mPtr);

}

}

return true;

}

}

4253f551e877

image

在Java层提取Message

public final class MessageQueue {

Message next() {

......

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();

}

// ptr 保存了 NativeMessageQueue的指针,调用nativePollOnce进行等待

nativePollOnce(ptr, nextPollTimeoutMillis);

synchronized (this) {

final long now = SystemClock.uptimeMillis();

Message prevMsg = null;

Message msg = mMessages;

if (msg != null && msg.target == null) {

// 尝试先从消息队列中寻找异步消息

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 {

//如果从消息队列中获取的Message小于当前时间,则返回给Looper进行派发和处理。

mBlocked = false;

if (prevMsg != null) {

prevMsg.next = msg.next;

} else {

mMessages = msg.next;

}

msg.next = null;//断开引用链,便于GC回收

msg.markInUse();

return msg;

}

} else {

// No more messages.

// 消息队列中没有更多的消息了。则进行长时间休眠。

// -1代表长时间等待。

nextPollTimeoutMillis = -1;

}

......

// 下面主要IdleHandler的相关逻辑

// 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 {

//这里函数的返回值,觉得后续是否还会调用该IdleHandler的方法。

keep = idler.queueIdle();

} catch (Throwable t) {

Log.wtf(TAG, "IdleHandler threw exception", t);

}

// queueIdle 返回false的时候,就会将其从ArrayList队列中移除掉,下次就不会再接收到函数调用。

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;

}

}

}

nativeWake函数分析

nativeWake函数分析

frameworks/base/core/jni/android_os_MessageQueue.cpp

class NativeMessageQueue : public MessageQueue, public LooperCallback {

static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {

NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr);

nativeMessageQueue->wake();

}

void NativeMessageQueue::wake() {

mLooper->wake();

}

}

system/core/libutils/Looper.cpp

void Looper::wake() {

......

uint64_t inc = 1;

//向管道的写端写入一个字符(旧版本是写入一个"W"字符)。

ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));

if (nWrite != sizeof(uint64_t)) {

......

}

}

//旧版

//父进程、子进程

void Looper::wake() {

#if DEBUG_POLL_AND_WAKE

ALOGD("%p ~ wake", this);

#endif

ssize_t nWrite;

do {

nWrite = write(mWakeWritePipeFd, "W", 1);

} while (nWrite == -1 && errno == EINTR);

if (nWrite != 1) {

if (errno != EAGAIN) {

ALOGW("Could not write wake signal, errno=%d", errno);

}

}

}

nativePollOnce函数分析

frameworks/base/core/jni/android_os_MessageQueue.cpp

class NativeMessageQueue : public MessageQueue, public LooperCallback {

static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,

jlong ptr, jint timeoutMillis) {

NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr);

nativeMessageQueue->pollOnce(env, obj, timeoutMillis);

}

void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {

......

mLooper->pollOnce(timeoutMillis);

......

}

}

system/core/libutils/Looper.cpp

inline int pollOnce(int timeoutMillis) {

return pollOnce(timeoutMillis, nullptr, nullptr, nullptr);

}

int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);

timeoutMillis:超时等待时间。

如果为-1,则表示无限等待,直到有事件发生为止。

如果值为0,则无需等待立即返回。

outFd:用来存储发生事件的那个文件描述符。

outEvents:用来存储在该文件描述符上发生了哪些事件,目前支持可读、可写、错误和中断4个事件。(从epoll事件对应而来)

outData:用来存储上下文数据,这个上下文数据是由用户在添加监听句柄时传递的,它的作用和 pthread_create 函数的最后

一个参数 parame 一样,用来传递用户数据。

int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {

int result = 0;

for (;;) { //无限循环

// mResponses 为 Vector数据结构。

while (mResponseIndex < mResponses.size()) {

const Response& response = mResponses.itemAt(mResponseIndex++);

int ident = response.request.ident;

if (ident >= 0) {

int fd = response.request.fd;

int events = response.events;

void* data = response.request.data;

if (outFd != nullptr) *outFd = fd;

if (outEvents != nullptr) *outEvents = events;

if (outData != nullptr) *outData = data;

return ident;

}

}

if (result != 0) {

if (outFd != nullptr) *outFd = 0;

if (outEvents != nullptr) *outEvents = 0;

if (outData != nullptr) *outData = nullptr;

return result;

}

result = pollInner(timeoutMillis);

}

}

int Looper::pollInner(int timeoutMillis) {

......

调用epoll函数等待,查看epoll函数返回结果;

超时、错误、有事件发生;

如果是管道读端有事件,则认为是控制命令,可以直接读取管道中的数据;(eventfd)

如果是其他fd发生事件,则根据Request构造Response,并push到Response数组中。

真正处理事件,首先处理Native的Message。调用Native Handler 的 handleMessage处理该Message。

处理Response数组中带有callback的事件。

}

Handler、Looper、MessageQueue、Thread关系

4253f551e877

image.png

一个线程里面有一个Looper。

一个Looper对应一个MessageQueue。

一个Looper可能对应多个Handler。

相同的Looper的Handler发消息,都发送到同一个MessageQueue。

MessageQueue处理完成后,分发消息会根据target字段,找到Handler的引用,并完成分发工作。

甜点

1. IdelHandler

public static interface IdleHandler {

boolean queueIdle();

}

当一个线程准备等待更多消息时,即其将消息分发完之后就会回调这个接口。

queueIdle返回false代表一次性,返回true可能有多次回调。

添加IdleHandler

public final class MessageQueue {

public void addIdleHandler(@NonNull IdleHandler handler) {

if (handler == null) {

throw new NullPointerException("Can't add a null IdleHandler");

}

synchronized (this) {

mIdleHandlers.add(handler);

}

}

}

2. 消息屏障

4253f551e877

image

Message类型分为3种类型:

normal 普通消息

barrier 消息屏障

async 异步消息

插入消息屏障

public final class MessageQueue {

public int postSyncBarrier() {

return postSyncBarrier(SystemClock.uptimeMillis());

}

private int postSyncBarrier(long when) {

// 按照时间排序,将这个msg插入到消息队列中

synchronized (this) {

final int token = mNextBarrierToken++;

final Message msg = Message.obtain();

msg.markInUse();

msg.when = when;

msg.arg1 = token;

Message prev = null;

Message p = mMessages;

if (when != 0) {

while (p != null && p.when <= when) {

prev = p;

p = p.next;

}

}

if (prev != null) { // invariant: p == prev.next

msg.next = p;

prev.next = msg;

} else {

msg.next = p;

mMessages = msg;

}

return token;

}

}

}

消息屏障有6点注意事项!

没有设置target。

消息屏障也是带着时间戳的,也是按时间来进行排序,只影响后面他后面的消息。

消息队列是可以插入多个消息屏障的。

插入到消息队列的时候,是没有唤醒线程的。

插入消息屏障的时候会返回一个token,后续撤除这个消息屏障,需要使用token去消息队列中查找。

消息屏障没有对外开放,要使用需要利用反射机制。

移除消息屏障

public final class MessageQueue {

//根据token移除消息屏障。

public void removeSyncBarrier(int token) {

// Remove a sync barrier token from the queue.

// If the queue is no longer stalled by a barrier then wake it.

synchronized (this) {

Message prev = null;

Message p = mMessages;

while (p != null && (p.target != null || p.arg1 != token)) {

prev = p;

p = p.next;

}

if (p == null) {

throw new IllegalStateException("The specified message queue synchronization "

+ " barrier token has not been posted or has already been removed.");

}

final boolean needWake;

if (prev != null) {

prev.next = p.next;

needWake = false;

} else {

mMessages = p.next;

needWake = mMessages == null || mMessages.target != null;

}

p.recycleUnchecked();

// If the loop is quitting then it is already awake.

// We can assume mPtr != 0 when mQuitting is false.

if (needWake && !mQuitting) {

nativeWake(mPtr);

}

}

}

}

处理屏障

next方法里面处理,具体逻辑为:

public final class MessageQueue {

Message next() {

for (;;) {

nativePollOnce(ptr, nextPollTimeoutMillis);

......

如果第一条消息是就是屏障,就往后面遍历查看是否有异步消息。

如果没有,就无限休眠,等待被别人唤醒。

如果有,就看这个消息触发时间还有多长,设置一个超时,继续休眠。

}

}

}

如果将消息插入到队列头部,不受消息屏障的影响,唤醒线程,去处理消息。

如果没有插入到队列头部,并且头部是消息屏障,此时插入普通消息不唤醒消息队列。

如果此时插入的是异步消息,并且插入的位置前面没有其他异步消息,则进行队列的唤醒。

Android中内存屏障使用例子

总结

4253f551e877

image

Java层提供了Looper类和MessageQueue类,其中Looper类提供循环处理消息的机制,以及插入、删除和提取消息的函数接口。

Handler常用于用户与MessageQueue处理相关。

MessageQueue内部通过mPtr变量保存了一个Native层的NativeMessageQueue对象。

NativeMessageQueue保存了一个Native层的Looper对象,该Looper从ALooper派生,提供pollOnce 和addFd等函数。

Java层有Message类和Handler类,而Native层也有对应的Message类和MessageHandler抽象类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值