美文网首页
handler消息队列无消息处理方案

handler消息队列无消息处理方案

作者: GoLearning轻松学 | 来源:发表于2022-01-22 07:20 被阅读0次
      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交出去,给别人用。

    相关文章

      网友评论

          本文标题:handler消息队列无消息处理方案

          本文链接:https://www.haomeiwen.com/subject/ybxyhrtx.html