時光飛逝,不知不覺寫完Handler系列文章已經用時一個月了。做爲我開始分析Android Framework源碼的敲門磚仍是遇到了不少挫折,尤爲是分析MessageQueue源碼時那種百思不得其解的疑惑困擾着我很長時間。不過當我想通了這其中的原理後那種酣暢淋漓的感受也讓我頗有成就感。java
Android 的工程師們充分利用了Java的高級語言特性,即類中持有着一個類自身的屬性做爲經典數據結構中的鏈表next
指針,以靜態屬性屬於類自己的特性實現了鏈表的表頭。這種模式給我了很大的啓發,讓我這種渣渣每逢想起都會驚訝「還有這種操做?」。緩存
爲何要有緩存池markdown
瞭解完Handler總體機制後我猜想,Message功能十分單一且狀態不多,它只是一個具體發送消息的載體,可是使用數量十分龐大,回收用過的Message不只能夠有效的減小重複消耗系統資源且回收它的成本很低,因此何樂而不爲呢?數據結構
誰負責回收Messageoop
咱們使用Message時候知道調用Message.obtain();
方法能夠從緩存池中取出一個Message,有存纔能有取,咱們何時回收它呢?從源碼中發現,Looper在分發Message給宿主Handler以後,肯定了Message已經完成了它的使命直接就會將它回收。因此咱們徹底不用擔憂這個,咱們發送的每一個消息最後都會被回收。性能
MessageQueue維持的消息隊列也是靠跟Message緩存池一樣的原理生成的,每次消息出隊時若是沒有合適的待取出消息就會阻塞線程等待有合適的消息。spa
很是奇怪的是,MessageQueue線程的方式不是傳統使用java實現的,而是經過JNI調用native層的C++代碼實現的,C++代碼中也實現了一套Looper+MessageQueue+Handler,阻塞線程的方式是調用Linux的監聽文件描述符ePoll實現的。線程
個人猜想是由於Java代碼須要通過JVM的幫助才能跟系統接觸,這一過程會消耗性能,而C++代碼則直接能夠繞過這一個環節。因此,使用C++代碼實現線程阻塞多是性能上的需求。指針
在沒有真正瞭解Handler的時候覺得Google的工程師們在Handler上使用了什麼了不得的技術呢,因此才推薦開發者們使用Handler來實現線程間通訊。code
其實呢?Android是事件型驅動的系統,剛建立一個應用程序的主線程裏就會被建立一個Looper來不斷接受各類事件,因此說若是咱們打開一個程序什麼都不操做,這個程序就有多是阻塞狀態的,由於他沒有任何事件須要去處理。反之,咱們在本身的UI線程裏執行一項耗時操做,主線程Looper一直在處理這個任務而沒法分身處理其它的事件這時候就有可能ANR了。
因此,不是Handler的技術多牛逼,是主線程用了Handler來通訊,你是用別的方法通訊有可能會影響主線程Looper的正常工做。