Android中Looper原理

参考:

https://www.zhihu.com/question/34652589 // Handler 

https://blog.csdn.net/rock_joker/article/details/76735333 // Linux pipe/epoll

https://www.cnblogs.com/coder2012/archive/2013/07/22/3204730.html 进程状态

 

1,从Handler到Looper

Android中Looper原理_第1张图片

 

    以上就是Handler机制的概要,每个部分都扮演着自己的角色

    * Handler:发送消息和最后接收并处理消息

    * Message:消息对象

    * MessageQueue:消息队列(未被CPU处理的消息,都放这了)

    * Looper:不断地循环MessageQueue,若有消息则执行,若无消息则阻塞

 

2,Looper一直循环,为什么不会死循环卡死,即:没有高频率占用CPU

1) Looper的调用

#ActivityThread.java::main()
    public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
		// 创建ActivityThread
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        ...
        Looper.loop(); // 消息循环
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

    可以看出,Looper.loop()之后,就抛出异常,所以按照现象,loop()中应该是一个永真循环(死循环,永不退出)

2) loop()循环的实现

#Looper.java::loop()
    public static void loop() {
        ...
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                return;
            }
            msg.target.dispatchMessage(msg); // 分发消息,等待实现处理
            msg.recycleUnchecked();
        }
    }
#MessageQueue.java::next()
    Message next() {
        ...
        for (;;) {
            nativePollOnce(ptr, nextPollTimeoutMillis); // 轮询到下一个消息
            synchronized (this) {
				... // 遍历下一个消息,若无消息,则继续;若有消息则返回Msg
            }
			...
		}
    }
#android_os_MessageQueue.cpp::android_os_MessageQueue_nativePollOnce()
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, jlong ptr, jint timeoutMillis) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr);
    nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
#android_os_MessageQueue.cpp::pollOnce()
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
    ...
    mLooper->pollOnce(timeoutMillis);
    ...
}	
#Looper.cpp::pollOnce()
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for (;;) {
        ... // 中间有 return result;
        result = pollInner(timeoutMillis);
    }
}
#Looper.cpp::pollInner()
int Looper::pollInner(int timeoutMillis) {
	...
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); // Poll.
    mLock.lock(); // Acquire lock.
    if (mEpollRebuildRequired) {
        mEpollRebuildRequired = false;
        rebuildEpollLocked();
    }
    ... // Handle all events and message
    mLock.unlock(); // Release lock.
	
	... // Invoke all response callbacks.
    return result;
}
#Looper.cpp::rebuildEpollLocked
void Looper::rebuildEpollLocked() {
    ...
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
	...
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
    for (size_t i = 0; i < mRequests.size(); i++) {
        ...
        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
    }
}

    * loop()中是一个永真循环,而每次调用next() 最终调用到pollInner(),执行 epoll_wait语句

    * epoll_wait、epolll_create、epoll_ctl涉及到Linux的pipe/epoll机制。大致功能是,当前线程会释放CPU资源进入休眠状态,直到有消息或事务发生,通过往pipe管道写端写入数据唤醒工作(epoll_wait得到执行)。即:epoll是阻塞的

    ==> 结论:Looper中执行一个永真循环,其中每次有消息则执行,无消息时,则阻塞。因此不会消耗大量CPU资源

 

3,拓展(while循环和占用CPU案例、进程状态和CPU调用关联)

1)while循环和占用CPU案例

#SampleA
	while (true) {
		index++;
		if (index > 1024) {
			index = 0;
		}
	}
#SampleB
	while (true) {
		Thread.sleep(1);
		
		index++;
		if (index > 1024) {
			index = 0;
		}
	}

    * SampleA会导致CPU占有率居高不下,SampleB对CPU占有率影响基本可以忽略不计

    * 原因:CPU执行频率以纳秒为单位而,而每次sleep 1秒,相当于阻塞当前线程,放弃占用CPU资源。从而对CPU占用率就变得极小

    

2)进程状态和CPU调用关联

Android中Looper原理_第2张图片

进程状态 CPU情况
运行 该进程正在被CPU执行
就绪 进程资源准备好了,进入队列排队,等待CPU执行;CPU在执行其它任务
阻塞 进程未准备好,需要等待信号,进入队列排队;CPU在执行其它任务

    总结一下:进程可以被执行时,CPU依照调度可以执行该任务(不一定执行);进程阻塞时,让出CPU
 

 

 

 

 

你可能感兴趣的:(Android_线程)