<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                文章出處:鏈接:https://www.zhihu.com/question/34652589/answer/90344494 要完全徹底理解這個問題,需要準備以下4方面的知識: 1. Process/Thread, 2. Android Binder IPC, 3. Handler/Looper/MessageQueue消息機制, 4. Linux pipe/epoll機制。 **總結一下樓主主要有3個疑惑:** 1. Android中為什么主線程不會因為Looper.loop()里的死循環卡死? 2. 沒看見哪里有相關代碼為這個死循環準備了一個新線程去運轉? 3. Activity的生命周期這些方法這些都是在主線程里執行的吧,那這些生命周期方法是怎么實現在死循環體外能夠執行起來的? ***** 針對這些疑惑, [@hi大頭鬼hi](https://www.zhihu.com/people/50b28faaec835947511e005cd6734484)、[@Rocko](https://www.zhihu.com/people/4897651cf72b010294463a1fd113af52)、[@陳昱全](https://www.zhihu.com/people/53013cf8f04bf168814156e563beb935) 大家回答都比較精煉,接下來我再更進一步詳細地一一解答樓主的疑惑: **(1) Android中為什么主線程不會因為Looper.loop()里的死循環卡死?** 這里涉及線程,先說說說進程/線程, * **進程**:每個app運行時前首先創建一個進程,**該進程是由Zygote fork出來的,用于承載App上運行的各種Activity/Service等組件**。 進程對于上層應用來說是完全透明的,這也是google有意為之,讓App程序都是運行在Android Runtime。 大多數情況一個App就運行在一個進程中,除非在AndroidManifest.xml中配置`Android:process`屬性,或通過JNI在native層去fork一個新的進程。 * **線程**:線程對應用來說非常常見,比如每次new Thread().start都會創建一個新的線程。**該線程與App所在進程之間資源共享,從Linux角度來說進程與線程除了是否共享資源外,并沒有本質的區別,都是一個task\_struct結構體**,**在CPU看來進程或線程無非就是一段可執行的代碼,CPU采用CFS調度算法,保證每個task都盡可能公平的享有CPU時間片**。 有了這么準備,再說說死循環問題: 對于線程既然是一段可執行的代碼,當可執行代碼執行完成后,線程生命周期便該終止了,線程退出。**而對于主線程,我們是絕不希望會被運行一段時間,自己就退出,那么如何保證能一直存活呢?簡單做法就是可執行代碼是能一直執行下去的,死循環便能保證不會被退出**,例如,binder線程也是采用死循環的方法,通過循環方式不同與Binder驅動進行讀寫操作,**當然并非簡單地死循環,無消息時會休眠**。 但這里可能又引發了另一個問題,**既然是死循環又如何去處理其他事務呢**?**通過創建新線程的方式**。 **真正會卡死主線程的操作是在回調方法onCreate/onStart/onResume等操作時間過長,會導致掉幀,甚至發生ANR,looper.loop本身不會導致應用卡死**。 **(2) 沒看見哪里有相關代碼為這個死循環準備了一個新線程去運轉?** 事實上,**會在進入死循環之前便創建了新binder線程,在代碼`ActivityThread.main()`中**: ~~~java public static void main(String[] args) { .... //創建Looper和MessageQueue對象,用于處理主線程的消息 Looper.prepareMainLooper(); //創建ActivityThread對象 ActivityThread thread = new ActivityThread(); //建立Binder通道 (創建新線程) thread.attach(false); Looper.loop(); //消息循環運行 throw new RuntimeException("Main thread loop unexpectedly exited"); } ~~~ **thread.attach(false);便會創建一個Binder線程(具體是指ApplicationThread,Binder的服務端,用于接收系統服務AMS發送來的事件),該Binder線程通過Handler將Message發送給主線程**,具體過程可查看 [startService流程分析](https://link.zhihu.com/?target=http%3A//gityuan.com/2016/03/06/start-service/),這里不展開說,簡單說Binder用于進程間通信,采用C/S架構。關于binder感興趣的朋友,可查看我回答的另一個知乎問題: [為什么Android要采用Binder作為IPC機制? - Gityuan的回答](https://www.zhihu.com/question/39440766/answer/89210950) 另外,**[ActivityThread](https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/app/ActivityThread.java)實際上并非線程,只是運行在主線程的對象**,不像HandlerThread類,**ActivityThread并沒有真正繼承Thread類,只是往往運行在主線程,給人以線程的感覺,其實承載ActivityThread的主線程就是由Zygote fork而創建的進程**。 * **主線程的死循環一直運行是不是特別消耗CPU資源呢?** 其實不然,這里就涉及到**Linux pipe/epoll機制**,簡單說就是在主線程的MessageQueue沒有消息時,便阻塞在loop的queue.next()中的nativePollOnce()方法里,詳情見[Android消息機制1-Handler(Java層)](https://link.zhihu.com/?target=http%3A//www.yuanhh.com/2015/12/26/handler-message-framework/%23next),此時主線程會釋放CPU資源進入休眠狀態,直到下個消息到達或者有事務發生,通過往pipe管道寫端寫入數據來喚醒主線程工作。 這里采用的epoll機制,是一種IO多路復用機制,可以同時監控多個描述符,當某個描述符就緒(讀或寫就緒),則立刻通知相應程序進行讀或寫操作,本質同步I/O,即讀寫是阻塞的。 **所以說,主線程大多數時候都是處于休眠狀態,并不會消耗大量CPU資源。** **(3) Activity的生命周期是怎么實現在死循環體(Looper.loop()里的死循環)外能夠執行起來的?** ActivityThread的內部類H繼承于Handler,通過handler消息機制,簡單說Handler機制是用于同一個進程的線程間通信。 **Activity的生命周期都是依靠主線程的Looper.loop,當收到不同Message時則采用相應措施:** 在H.handleMessage(msg)方法中,根據接收到不同的msg,執行相應的生命周期。 * 比如收到msg=H.LAUNCH\_ACTIVITY,則調用ActivityThread.handleLaunchActivity()方法,最終會通過反射機制,創建Activity實例,然后再執行Activity.onCreate()等方法; * 再比如收到msg=H.PAUSE\_ACTIVITY,則調用ActivityThread.handlePauseActivity()方法,最終會執行Activity.onPause()等方法。 上述過程,我只挑核心邏輯講,真正該過程遠比這復雜。 **主線程的消息又是哪來的呢**?當然是**App進程中的其他線程通過Handler發送給主線程**,請看接下來的內容: **最后,從進程與線程間通信的角度,****通過一張圖****加深大家對App運行過程的理解:** ![](https://picb.zhimg.com/80/7fb8728164975ac86a2b0b886de2b872_720w.jpg?source=1940ef5c) * **system\_server進程是系統進程** Java FrameWork框架的核心載體,里面運行了大量的系統服務,比如這里提供ApplicationThreadProxy(簡稱ATP),ActivityManagerService(簡稱AMS),這個兩個服務都運行在system\_server進程的不同線程中,由于ATP和AMS都是基于IBinder接口,都是binder線程,binder線程的創建與銷毀都是由binder驅動來決定的。 * **App進程則是我們常說的應用程序**,主線程主要負責Activity/Service等組件的生命周期以及UI相關操作都運行在這個線程; 另外,每個App進程中至少會有兩個binder線程 [ApplicationThread](https://www.androidos.net.cn/android/8.0.0_r4/xref/frameworks/base/core/java/android/app/ActivityThread.java)(簡稱AT,它是ActivityThread的內部類)和ActivityManagerProxy(簡稱AMP,它是[ActivityManagerNative](https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/app/ActivityManagerNative.java)的內部類),除了圖中畫的線程,其中還有很多線程,比如signal catcher線程等,這里就不一一列舉。 Binder用于不同進程之間通信,由一個進程的Binder客戶端向另一個進程的服務端發送事務,比如圖中線程2向線程4發送事務;而handler用于同一個進程中不同線程的通信,比如圖中線程4向主線程發送消息。 **結合圖說說Activity生命周期,比如暫停Activity,流程如下:** 1. 線程1的AMS中調用線程2的ATP;(由于同一個進程的線程間資源共享,可以相互直接調用,但需要注意多線程并發問題) 2. 線程2通過binder傳輸到App進程的線程4; 3. 線程4通過handler消息機制,將暫停Activity的消息發送給主線程; 4. 主線程在looper.loop()中循環遍歷消息,當收到暫停Activity的消息時,便將消息分發給ActivityThread.H.handleMessage()方法,再經過方法的調用,最后便會調用到Activity.onPause(),當onPause()處理完后,繼續循環loop下去。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看