public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
AndroidKeyStoreProvider.install();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
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和ThreadLocal关联起来,保证looper的唯一性
}
/**
* Sets the value of this variable for the current thread. If set to
* {@code null}, the value will be set to null and the underlying entry will
* still be present.
*
* @param value the new value of the variable for the caller thread.
*/
public void set(T value) {
Thread currentThread = Thread.currentThread();//拿到当前的线程
Values values = values(currentThread);//获取这个线程的Values对象
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);//把threadLocal当作key,Looper当作value存储起来
}
/**
* Adds an entry during rehashing. Compared to put(), this method
* doesn't have to clean up, check for existing entries, account for
* tombstones, etc.
*/
void add(ThreadLocal<?> key, Object value) {
for (int index = key.hash & mask;; index = next(index)) {//根据key获取index下标
Object k = table[index];
if (k == null) {
table[index] = key.reference;//index未知存储key
table[index + 1] = value;//index+1位置存储value
return;
}
}
}
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和ThreadLocal关联起来,保证looper的唯一性
}
我们从上面ThreadLocal的源码分析知道ThreadLocal是通过set的方式将sThreadLocal和looper绑定起来的。我们再看到prepare里有一个 if (sThreadLocal.get() != null) {这样的判断,它的意思是通过ThreadLocal去取对应的looper,如果已经存在了,就会抛出"Only one Looper may be created per thread"异常,所以它保证了每个ThreadLocal的values的table数组里存储的looper是唯一的,也就是说ThreadLocal和Looper是一一对应的,不会重复的,又因为每个Thread都会有一个ThreadLocal.Values localValues的成员变量,所以
#结论一:不管是主线程还是非主线程,每一个Thread对应了一个唯一的looper。(当然一个线程可以创建多个Handler)。
分析完主线程里的prepareMainLooper方法,我们再进入主线程里的另外一个方法Looper.loop()里去看看,所以我们进入Looper类的looper方法去分析:
public static void loop() {
final Looper me = myLooper();//保证Looper的唯一性
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue v = me.mQueue;//保证MessageQueue的唯一性
// 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();
for (;;) {
//死循环里从MessageQuene里取消息,没有消息就会一直等待
//如果没有要执行的消息,就会一直在等待,所以主线程永远不会退出,有消息就执行消息,没消息就一直等待
//这就是主线程永远不需要创建handle,但可以一直执行,而且looper一直在工作的原因
//主线程不是在工作,就是在等待
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, incase a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);//通过调用target(实际是handle实例)的dispatchMessage传回给handle
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();//msg会去回收msg
}
}
我们看到final Looper me = myLooper();这一句,一开始先是去拿到一个looper对象,我们进入myLooper()看看是怎么拿到的?
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();//从ThreadLocal里拿到Looper对象
}
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
如果你的looper是空,会报异常,提示你"No Looper; Looper.prepare() wasn't called on this thread.",小伙伴么,这个异常我们在刚刚开始学习多线程通信的时候是不是常常遇到啊?我们想实现两个子线程的通信,是不是要在其中一个子线程里调用looper.loop方法啊?我们在调用looper.loop之前是不是要先调用Looper.prepare()?所以你看这里,如果你在looper.loop之前不调用Looper.prepare()是会报异常的,我们继续往下看,然后再通过looper对象,拿到MessageQueue对象,我们先去看看这个MessageQueue对象怎么拿到的?进入到looper的构造方法看看
/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
void recycleUnchecked() {//
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
//享元模式(并不是销毁msg,而是把msg里的各种成员变量置为null,下次有新的消息的时候,直接复用
//,而不是再去new msg,减少了内存碎片的出现,减少了内存抖动,提高了程序的性能
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
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();
}
//native函数没进入等待的方法nextPollTimeoutMillis=-1会一直等待,
//nextPollTimeoutMillis>0会等待nextPollTimeoutMillis时间
//nextPollTimeoutMillis = 0;不会等待
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) {
// 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) {
//如果当前的时间now还没达到消息执行的时间when,就开始等待
if (now < msg.when) {//msg.when是当前时间加上消息的延迟时间,在handle发送消息的时候会带过来(SystemClock.uptimeMillis() + delayMillis)
// Next message is not ready. Set a timeout to wake up when it is ready.
//等待的时间就是msg.when - 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;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {//msg==null没有消息的时候nextPollTimeoutMillis为-1
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
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)) {//消息为空走这个if
//将 mIdleHandlers.size()赋值给pendingIdleHandlerCount,因为大多数情况下 mIdleHandlers.size()是为0的,所以
//pendingIdleHandlerCount大多数情况下等于0,也就是大多数情况下会走下面pendingIdleHandlerCount <= 0这个if,
//所以主线程大多数是不走这个死循环的会直接continue,直接continue也就是extPollTimeoutMillis为-1
//extPollTimeoutMillis为-1传入native等待函数的时候native等待函数会一直等待。
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {//消息不为空走这个if,
// No idle handlers to run. Loop and wait some more.
mBlocked = true;//阻塞标志置为truecontinue;//continue就会退出当前的循环继续走循环的下一个,所以循环末尾的 nextPollTimeoutMillis = 0;不会走,所以调用前面的native休眠的方法,进入等待
}
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;
}
}
//生产者:消息是按时间排序的,越早进来的消息(加上消息延迟时间),越排在队伍的前面
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();
returnfalse;
}
msg.markInUse();
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;//如果线程是阻塞的,就把needWake置为true,在下面唤醒线程
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
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;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);//native函数唤醒主线程,让主线程工作,不再等待
}
}
return true;
}
if (p == null || when == 0 || when < p.when) {//当前要执行的消息(队头消息)为空,说明消息已经被取走了
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;//把新消息赋值给队头消息
needWake = mBlocked;//如果线程是阻塞的,就把needWake置为true,在下面唤醒线程
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
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;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);//native函数唤醒主线程,让主线程工作,不再等待
}
我们直接看到 if (p == null || when == 0 || when < p.when) 这个判断的意思是:当前要执行的消息(队头消息)为空,说明消息已经被取走了,然后会把把新消息赋值给队头消息,然后把阻塞标志mBlocked的值赋给needWake,如果阻塞表示是ture,就会调用nativeWake唤醒线程,让线程不再等待。大家还记得么?在next取出方法的时候,如果没消息或者消息还没到达发送时间我们最后是把mBlocked置为true的,这里加入消息的方法enqueueMessage刚刚好利用了这个标志,如果当前线程的消息又来了,就把线程唤醒。这个配合就实现了整个handler的消息收发机制,也解答了loop里为什么Message msg = queue.next(); // might block这句话可能会阻塞的原因,这个实现机制是不是特别精辟。
到此,整个handler消息的收发机制都讲完了,相信大家都能回答为什么handler机制能实现线程间的内存共享这个问题了。