?引言: 線程是一段可執(zhí)行的代碼,當可執(zhí)行代碼執(zhí)行完成后蟆沫,線程生命周期便該終止了籽暇,線程也即退出了。
帶著兩個問題思考:
1饭庞、代碼執(zhí)行完了線程生命周期便終止戒悠,那為什么主線程能一直執(zhí)行而不退出呢?
2舟山、Android 是如何實現(xiàn)線程同步的绸狐?
此過程涉及到幾個類,先做普及 ActivityThread: ActivityThread.main() 函數(shù)作為程序入口累盗。
Looper: Looper.loop() 死循環(huán)寒矿,用于保證該線程生命周期一直執(zhí)行,不會退出若债。
ThreadLocal: 存放 Looper符相,可實現(xiàn)線程共享。
MessageQueue: 存放有序的 Message蠢琳,管理任務
Message: 消息
Handler: 發(fā)送消息啊终,處理任務(handleMessage() 方法)
public class ThreadLocal<T> {
...
public T get() {
//以當前線程為 key 獲取 value,實現(xiàn)線程共享
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;
}
}
return setInitialValue();
}
}
從主線程開始執(zhí)行到 Handler 處理任務分析:
應用的入口從 ActivityThread.main() 開始執(zhí)行。當前運行的線程即為主線程(mainThread)傲须。
public final class ActivityThread extends ClientTransactionHandler {
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
Looper.loop();
}
}
1 > 在 main() 中調用 Looper.prepareMainLooper() 時實際是通過 Looper.prepare(false) 創(chuàng)建 Looper 蓝牲,并將 looper 保存在 ThreadLocal 中。存放在 ThreadLocal 中的好處是可以線程共享泰讽,即只要在當前線程中就可以獲取到 Looper 對象搞旭。
2 > Looper 對象初始化時生成 MessageQueue 對象,MessageQueue 是一個單向鏈表菇绵,用來存放 message 并指向下一個 messgae,這種結構保證了消息順序執(zhí)行镇眷。
public final class Looper {
//單例咬最,存放各個線程中 Looper 對象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
...
//消息隊列,用來存放 message
final MessageQueue mQueue;
final Thread mThread;
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//創(chuàng)建 Looper 并存放在 sThreadLocal 中
sThreadLocal.set(new Looper(quitAllowed));
}
//獲取 當前 Looper 對象
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
public final class MessageQueue {
Message mMessages;
}
3 > Looper.loop() 通過死限循環(huán) 調用 queue.next() 方法獲取 message 信息欠动。
public final class Message implements Parcelable {
//指向下一個消息
Message next;
//發(fā)送消息的 Handler 永乌,用于處理任務
Handler target;
}
public final class Looper {
public static void loop() {
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;
...
//死循環(huán)調用 queue.next() 獲取 message
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
return;
}
...
try {
//如果有 msg 不為空惑申,調用 target 即 handler 的 dispatchMessage()
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
}
...
msg.recycleUnchecked();
}
}
}
public class Handler {
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
...
} else {
...
//即各 Handler 處理任務的邏輯
handleMessage(msg);
}
}
}
public final class MessageQueue {
Message next() {
...
for (;;) {
...
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;
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.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
...
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
msg.markInUse();
return msg;
}
} else {
...
}
}
...
}
}
}
從 Handler 發(fā)送消息分析:
Handler 初始化時會通過 Looper.myLooper() 獲取當前線程的 Looper 對象,并獲取到 Looper 中的 MessageQueue 對象翅雏。由此可以猜測 當 handler.sendMessage(Message msg) 時發(fā)送的消息會被存放在 MessageQueue 中圈驼,與上面分析 MessageQueue.next 獲取消息對應。
public class Handler {
//通過 Looper.myLooper() 獲取創(chuàng)建該對象時
final Looper mLooper;
//用于存放 message
final MessageQueue mQueue;
public Handler(Callback callback, boolean async) {
//創(chuàng)建 Handler 時望几,Handler 會獲取到當前線程的 Looper 對象绩脆,并獲取到 MessageQueue
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;
}
}
發(fā)送消息 sendMessage()
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
...
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
//即 Looper 中的 MessageQueue
MessageQueue queue = mQueue;
...
return enqueueMessage(queue, msg, uptimeMillis);
}
下一步 msg.target = this 很重要
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//將當前 handler 對象賦值給 message.target,此操作是為了綁定 handler 橄抹,用于處理消息時分發(fā)給當前 Handler
msg.target = this;
...
return queue.enqueueMessage(msg, uptimeMillis);
}
以上是 handler.sendMessage 發(fā)送消息時將 message 發(fā)送給 messageQueue 對象靴迫,并將自身賦值給 message.target 與 message 綁定,綁定是為了在處理 message 時便于分辨執(zhí)行特定的 handler.handleMessage() 方法楼誓。
再看 MessageQueue 中 enqueueMessage(msg, uptimeMillis) 方法
boolean enqueueMessage(Message msg, long when) {
...
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
...
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
...
}
msg.next = p;
prev.next = msg;
}
...
}
return true;
}
enqueueMessage 只是通過 when 即 delayMillis 延遲處理的時間長短給插入的 message 排序玉锌。
以上分別分析了 處理任務與發(fā)送消息的 流程,流程如下:
ActivityThread.main() --> Looper.prepareMainLooper() --> Looper.loop() --> queue.next() --> msg.target.dispatchMessage() --> handler. dispatchMessage() --> handler. handleMessage()
回到開始提出的兩個問題疟羹,通過分析可以得出以下結論:
問:1主守、為什么主線程能一直執(zhí)行而不退出?
答: Looper.loop() 中通過死循環(huán)讓程序一直執(zhí)行榄融,不會退出参淫。并會持續(xù)調用 MessageQueue.next() 方法獲取 message。
問:2剃袍、Android 是如何實現(xiàn)線程同步的黄刚?
答: 不同線程中發(fā)送的消息都是發(fā)送到 創(chuàng)建 Handler 時所在的線程的 MessageQueue 對象中,通過 ThreadLocal 會獲取該線程中的 Looper 和 MessageQueue民效。當消息插入至 MessageQueue 中時憔维, MessageQueue.next() 會獲取到 message ,之后會調用 message.target.dispatchMessage()畏邢,最后調用 handleMessage() 處理任務业扒。
此過程中涉及到 IdleHandler 、和 線程掛起 nativePollOnce() 將另作篇幅分析