new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
myHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
return false;
}
});
Looper.loop();
}
});
在子线程中用Looper的时候,run方法会一直执行Looper里面的,Looperr里面有个loop()函数,里面是一个for循环,而且是一个死循环,如果我的消息队列没有消息会发生什么事情?当Looper去消息队列取消息的时候,queue.next(),这里有一个注解,//might block,如果这个消息队列没有消息就会一直阻塞在nativePollOnce这里,一直在等待。
public final class MessageQueue {
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
@UnsupportedAppUsage
Message next() {
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) {
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 {
// 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 {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
}
意味着queue.next()会一直等待,这个时候就会block住,换句话说,这里block住,意味着Lopper一直在这里面等待,run函数一直处于等待状态,run会一直被执行,线程不会销毁,结果内存泄漏,线程一直处于执行状态,所以这时候,我们线程所有的上下文全部都会在内存当中,那么这样自会导致CPU浪费,内存浪费
解决办法:
在Looper里面有一个quite(),会调用nativeWake,nativePollOnce是出于等待,nativeWake是唤醒,唤醒之后往下面执行,最后next返回null,loop循环就会退出,Looper就推出,run方法往下执行,接着就会释放内存,把CPU交出去,给别人用。
网友评论