前言
作為一只小菜鳥,在閱讀到Android MediaPlayer相關(guān)的Nuplayer代碼的時候,發(fā)現(xiàn)函數(shù)的調(diào)用不再是A call B了,閱讀起來比較痛苦。
究其原因,是因為采取了一種消息傳遞機制來控制流程。對于熟悉多線程的童鞋來說,這個并不復(fù)雜,也可以說很簡單。但是對于我這種剛剛接觸Android、多線程的小菜鳥來說,還是值得研究一下的。
AMessage、AHandler、ALooper是什么?
我個人習(xí)慣從字面意思入手。Message:消息。Handler:處理。ALooper:循環(huán)。這里可以給出一個不恰當(dāng)?shù)谋确健?/p>
比如在最近很火的某貓超市的自動送貨流水線中,一個裝有各種各樣?xùn)|西的包裹是一個AMessage的話。那么一個傳送履帶就是一個ALooper,它將各式各樣的AMessage傳遞給需要進行下一步操作的快遞員AHandler。那么這樣子,一個完整的快遞送貨就運轉(zhuǎn)起來了。
同樣,在NuPlayer中,各種信息(int,string、buffer等(通過鍵值對對應(yīng)起來,方便使用時查找))都被設(shè)置在new出來的一個AMessage的成員變量中。
然后啟動一個ALooper(ALooper::LooperThread是繼承于Thread的),并且把AHandler注冊其中(某通的快遞員不能來某貓的超市提取貨物吧)。
這樣,當(dāng)某一線程中的函數(shù)需要另一函數(shù)(有可能是另一線程中的,也有可能就是本線程中的)做事情的時候,就會經(jīng)過AMessage所在的ALooper發(fā)送給指定的AHandler來處理。這樣,一次消息傳遞就完成了。
當(dāng)然,也有某個函數(shù)處理完了某事,需要向調(diào)用它函數(shù)發(fā)送Message,這個之后會具體分析。這里,還需要明確兩點概念:
一個ALooper消息隊列中可以有多個AHandler注冊其中,但是一個AHandler不能注冊在多個ALooper下。(一家快遞公司能有很多名快遞員,但是這些快遞員中的一人是不能在多家快遞公司任職的)
ALooper啟動后(線程啟動),會不斷輪詢,有AMessage,就拋給指定的AHandler處理。并且在發(fā)現(xiàn)自己的消息隊列中沒有任何消息時,會等待,不會一直跑,從而降低CPU的占用率
這里再給出兩張圖,加深童鞋們的理解(因為手笨,畫不好圖,就借用別人的圖了)。


為什么需要AMessage、AHandler、ALooper?
就我個人理解來說,Nuplayer在播放的過程中,大概會有7個線程之多,這么多線程,如果是異步操作,那么還不是那么復(fù)雜。但是如果要求同步操作,那對于我這種小菜鳥來說是不好實現(xiàn)的。
這里大概有童鞋要問,什么是同步,什么是異步?
假如晚上我邀請張三吃飯,然后等待張三忙完在和他一起去(等待他處理完其他事情,再處理我的請求),這是同步。
假如晚上我邀請張三吃飯,不管他有沒有在忙,我先走了(我請求發(fā)出了,然后繼續(xù)做接下來的事情),這是異步。
好,有了同步和異步的概念,我們就可以想象,如果要通過加鎖mutex的方式來處理7個以上干不同活的人的相互請求時,是不是很難控制,很容易死鎖,所以在NuPlayer中,引入了AMessage、AHandler、ALooper這三個類,來處理線程中的同步和異步問題。
寫在最后
第一次寫技術(shù)文章,思路和排版想必都比較混亂,萬事開頭難,希望能堅持下去,并且文章的質(zhì)量越來越高_
參考:
http://blog.csdn.net/harman_zjc/article/details/53397945