更多面试题请看这里:https://interview.raoyunsoft.com/
核心组件关系
-
Message
消息的载体,包含任务数据和目标Handler信息。它在Handler机制中贯穿始终,本质是一个链表节点。
-
Handler
对外的操作接口,主要职责:
- 生产者:通过
sendMessage()
/post()
向MessageQueue发送消息 - 处理器:在目标线程执行
handleMessage()
回调处理任务 - 内存管理:通过
obtain()
复用Message对象减少内存分配
- 生产者:通过
-
MessageQueue
消息容器,本质是优先级队列(按
when
时间排序)。核心能力:- 消息入队:
enqueueMessage()
- 消息出队:
next()
- 空闲任务管理:
addIdleHandler()
- 消息入队:
-
Looper
消息循环引擎,关键作用:
- 消费者:通过
loop()
无限循环调用queue.next()
取消息 - 线程绑定:通过
ThreadLocal
实现线程单例 - 消息分发:调用
msg.target.dispatchMessage()
触发处理
- 消费者:通过
工作流程
Handler发送Message Message入队 MessageQueue Looper循环 Message出队 Handler.handleMessage
并发安全实现机制
当多线程同时操作MessageQueue(生产者线程入队,Looper线程出队),通过同步锁+等待释放策略避免死锁:
关键代码实现
java
// 入队操作(生产者线程)
boolean enqueueMessage(Message msg, long when) {
synchronized (this) { // 获取互斥锁
// ... 消息插入队列逻辑
if (needWake) nativeWake(ptr); // 唤醒Looper线程
}
return true;
}
// 出队操作(Looper线程)
Message next() {
for (;;) {
nativePollOnce(ptr, timeout); // 释放CPU进入等待(不持有锁!)
synchronized (this) { // 获取锁后操作队列
// ... 查找可用Message
if (msg != null) return msg;
}
}
}
安全机制详解
-
锁分离设计
synchronized(this)
保护队列操作临界区nativePollOnce()
在同步块外部执行等待
-
避免死锁流程
生产者线程 MessageQueue Native层 Looper线程 尝试获取锁 获得锁 插入消息 nativeWake() 释放锁 nativePollOnce() 等待 唤醒(收到event) 尝试获取锁 获得锁 取出消息 释放锁 生产者线程 MessageQueue Native层 Looper线程
-
Native层协作
nativePollOnce()
:通过Linux epoll机制释放CPUnativeWake()
:向eventfd写入数据触发唤醒
关键点 :当队列为空时,Looper在
nativePollOnce()
中释放CPU资源并等待,此时不持有Java层锁,允许生产者线程随时入队新消息。唤醒后重新竞争锁执行出队操作。
典型应用场景
java
// 工作线程发送任务
new Thread(() -> {
Message msg = handler.obtainMessage();
msg.obj = "Data from worker";
handler.sendMessage(msg); // 安全入队
}).start();
// 主线程Handler处理
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
String data = (String) msg.obj;
textView.setText(data); // 更新UI
}
};
这种机制保证了跨线程通信的安全性和高效性,是Android事件驱动的核心基础。