androidhandler多線程
Ⅰ Android的handler機制的原理
Android的handler機制的原理分為非同步通信准備,消息發送,消息循環,消息處理。
1、非同步通信准備
在主線程中創建處理器對象(Looper)、消息隊列對象(Message Queue)和Handler對象。
2、消息入隊
工作線程通過Handler發送消息(Message) 到消息隊列(Message Queue)中。
3、消息循環
消息出隊: Looper循環取出消息隊列(Message Queue) 中的的消息(Message)。
消息分發: Looper將取出的消息 (Message) 發送給創建該消息的處理者(Handler)。
4、消息處理
處理者(Handler) 接收處理器(Looper) 發送過來的消息(Message),根據消息(Message) 進行U操作。

handler的作用
handler是android線程之間的消息機制,主要的作用是將一個任務切換到指定的線程中去執行,(准確的說是切換到構成handler的looper所在的線程中去出處理)android系統中的一個例子就是主線程中的所有操作都是通過主線程中的handler去處理的。
Handler的運行需要底層的 messagequeue和 looper做支撐。
Ⅱ Android中的特殊線程——HandlerThread
一般我們想要執行耗時操作都會想開段晌仔啟Thread子線程去處理,但是多次創建和銷毀線程是很耗系統資源的。為了解決這一問題,我們可以自己構建一個循環線程,在線程當中創建一個Looper輪循器,來進行消息的輪循, 當有耗時任務需要投放到該循環線程時,線程就會執行耗時任務,任務執行完成之後,線程又會處於阻塞等待狀態,不會馬上銷毀掉,直到下一個耗時任務被投放進來;即通過阻塞和等待來保證性能最優,為此Google為我們封裝好了HandlerThread框架。
  
 HandlerThread本質上就是一個Thread子線程,不同的是在Thread內部有一個Looper開啟了輪循器;
   HandlerThread = Handler + Thread + Looper 
  由於一般的Thread沒有開啟Looper輪循器,所以不能在子線程中創建handler,因為沒有對應的MessageQueue與handler相關聯,而MessageQueue是由Looper進行維護的;如果想在子線程中創建handler,必須先通過Looper.prepare()創建謹此一個Looper,再通過Looper.loop()開啟循環,才能使用Handler。
  
 1、HandlerThread本質上是一個線程類,繼承了Thread;
  2、HandlerThread有自己的內部Looper對象,可以進行loop循環;所以在HandlerThread中可以創建handler來發送和處理消息;
  3、通過獲取HandlerThread的Looper對象傳遞給Handler,可以在handleMessage()中執行非同步操作;
  4、handler中的looper默認綁定了UI線程的MessageQueue,對於非UI線程想使用MessageQueue機制的,HandlerThread的內部Looper最適合,它不會干擾和阻塞UI線程,減少了對性能的消耗,握汪但是處理效率低;
  5、HandlerThread是一個串列隊列,會比較穩定;
Ⅲ 關於Android Handler與Message的多線程消息的處理,為什我以下代碼會死掉 請高手看看,謝謝。
1.線程沒有終止條件,會一直給主線程發消息,主線程不停的調用handleMessage代碼,很容易ANR(應用程序不響應)
2.handler.obtainMessage()得到message對象比new Message();更高效
Ⅳ Android面試必問handler機制淺析
Handler是Android中的非同步消息處理機制。當發送一個消息之後,這個消息是進入一個消息隊列(MessageQueue),在消息隊列中通過Looper去循環的獲取隊列中的消息,然後將消息分派給對應的處理者進行處理。
  
 Message:存儲需要處理操作的信息
  
 MessageQueue:先進先出,存儲handler發送過來的消息
  
 Looper:循環器,它是消息隊列和handler的通信媒介,1:循環的取出消息隊列中的消息;2:將取出的消息發送給對應的處理者
  
 Handler:主線程和子線程的通信媒介,1:添加消息到消息隊列; 2:處理循環器分派過來的消息
  
 在handler機制中,Looper.loop方法會不斷循環獲取Message, 其中的消息的獲取是通過調用MessageQueue的next()方法獲取的,而該方法會調用nativePollOnce()方法 ,這是一個native方法。底層的實現涉及到Linux pipe/epoll機制,nativePollOnce()被阻塞時,主線程會釋放CPU資源,進入休眠狀態. 直到下個消息到達或者有事務發生,會通過pipe管道寫端寫入數據來喚醒looper工作。
  
 Android6.0及以前的版本使用管道與epoll來完成Looper的休眠與喚醒的
  
 Android6.0及以後的版本使用eventfd與epoll來完成Looper的休眠與喚醒的
  
 如果不處理的話,會阻塞線程,處理方案是調用Looper的quit()(清空所有的延遲和非延遲的消息)和quitSafely()(只清空延遲消息); 這個方法會調用MessageQueue的quit()方法,清空所有的Message,並調用nativeWake()方法喚醒之前被阻塞的nativePollOnce(),使得方法next()方法中的for循環繼續執行,接下來發現Message為null後就會結束循環,Looper結束。如此便可以釋放內存和線程
  
 同進程線程間內存共享,通過handler通信,消息的內容是不需要從一個線程拷貝到另一個線程,因為兩個線程間可使用的內存是同一個區域。(注意:線程私有區域ThreadLocal)
  
 管道的作用就是當一個線程准備好Message,並放入消息池,這時需要通知了一個線程B去處理這個消息。線程A向管道的寫端寫入數據,管道有數據便會喚醒線程B去處理消息。管道的作用是用於通知另一個線程的,這便是最核心的作用。
                                          
 從內存角度,通信過程中binder涉及到一次內存拷貝,handler機制中的Message根本不需要拷貝,本身就是在同一片內存。
  
 從CPU角度,為了Binder通信底層驅動還需要創建一個binder線程池,每次通信涉及binder線程的創建和內存的分配等比較浪費CPU資源
  
 原因:handler發送的消息在當前handler的消息隊列中,如果此時activity被finish掉了,那麼消息隊列的消息依舊由handler進行處理,若此時handler申明為內存類(非靜態內部類),內部類持有外部類的實例引用,這樣在GC垃圾回收時發現Activity還有其他引用存在,因而就不會去回首這個Activity,進而導致Activity泄漏。
  
 方法:使用靜態內部類,並且使用WeakReference包裹外部類的對象。首先靜態內部類不持有外部類的引用,使用靜態的handler不會導致activity的泄漏,handler定義static的同時,還要用WeakReference包裹外部類的對象。
Ⅳ 安卓的handler裡面的postDelay函數能不能用於多線程
android在謹桐敬主線程中使用handle.postdelay做延時操作對主線程資源消耗不大,因為handler中有一個消息池祥慎,是靜態的消息池, 建議輪此去了解一下Android中的Handler, Looper, MessageQueue之間的關系就知道了.
Ⅵ Android多線程的四種方式:Handler、AsyncTask、ThreadPoolExector、IntentService
     非同步通信機制,將工作線程中需更新UI的操作信息 傳遞到 UI主線程,從而實現 工作線程對UI的更新處理,最終實現非同步消息的處理。Handler不僅僅能將子線程的數據傳遞給主線程,它能實現任意兩個線程的數據傳遞。
  
  (1)Message 
  
     Message 可以在線程之間傳遞消息。可以在它的內部攜帶少量數據,用於在不同線程之間進行數據交換。除了 what 欄位,還可以使用 arg1 和 arg2 來攜帶整型數據,使用 obj 來攜帶 Object 數據。
  
  (2) Handler 
  
     Handler 作為處理中心,用於發送(sendMessage 系列方法)與處理消息(handleMessage 方法)。
  
  (3) MessageQueue 
  
     MessageQueue 用於存放所有通過 Handler 發送的消息。這部分消息會一直存放在消息隊列中,直到被處理。每個線程中只會有一個 MessageQueue 對象
  
  (4) Looper 
  
     Looper 用於管理 MessageQueue 隊列,Looper對象通過loop()方法開啟了一個死循環——for (;;){},不斷地從looper內的MessageQueue中取出Message,並傳遞到 Handler 的 handleMessage() 方法中。每個線程中只會有一個 Looper 對象。
  
     AsyncTask 是一種輕量級的任務非同步類,可以在後檯子線程執行任務,且將執行進度及執行結果傳遞給 UI 線程。
  
  (1)onPreExecute() 
  
     在 UI 線程上工作,在任務執行 doInBackground() 之前調用。此步驟通常用於設置任務,例如在用戶界面中顯示進度條。
  
  (2)doInBackground(Params... params) 
  
     在子線程中工作,在 onPreExecute() 方法結束後執行,這一步被用於在後台執行長時間的任務,Params 參數通過 execute(Params) 方法被傳遞到此方法中。任務執行結束後,將結果傳遞給 onPostExecute(Result) 方法,同時我們可以通過 publishProgress(Progress) 方法,將執行進度發送給 onProgressUpdate(Progress) 方法。
  
  (3)onProgressUpdate(Progress... values) 
  
     在 UI 線程上工作,會在 doInBackground() 中調用 publishProgress(Progress) 方法後執行,此方法用於在後台計算仍在執行時(也就是 doInBackgound() 還在執行時)將計算執行進度通過 UI 顯示出來。例如,可以通過動畫進度條或顯示文本欄位中的日誌,從而方便用戶知道後台任務執行的進度。
  
  (4)onPostExecute(Result result) 
  
     在 UI 線程上工作,在任務執行完畢(即 doInBackground(Result) 執行完畢)並將執行結果傳過來的時候工作。
  
  使用規則: 
  
 (1)AsyncTask 是個抽象類,所以要創建它的子類實現抽象方法
  
 (1)AsyncTask 類必須是在 UI 線程中被載入,但在Android 4.1(API 16)開始,就能被自動載入完成。
  
 (2)AsyncTask 類的實例對象必須在 UI 線程中被創建。
  
 (3)execute() 方法必須是在 UI 線程中被調用。
  
 (4)不要手動調用方法 onPreExecute()、onPostExecute()、doInBackground()、onProgressUpdate()
  
 (5)任務只能執行一次(如果嘗試第二次執行,將拋出異常)。即一個AsyncTask對象只能調用一次execute()方法。
  
  原理: 
  
           其源碼中原理還是 Thread 與 Handler 的實現,其包含 兩個線程池,一個 Handler,如下所示:
  
 名稱類型作用
  
 SERIAL_EXECUTOR線程池分發任務,串列分發,一次只分發一個任務
  
 THREAD_POOL_EXECUTOR線程池執行任務,並行執行,執行的任務由 SERIAL_EXECUTOR 分發
  
 InternalHandlerHandler負責子線程與主線程的溝通,通知主線程做 UI 工作
                                                                                  
     一方面減少了每個並行任務獨自建立線程的開銷,另一方面可以管理多個並發線程的公共資源,從而提高了多線程的效率。所以ThreadPoolExecutor比較適合一組任務的執行。Executors利用工廠模式對ThreadPoolExecutor進行了封裝。
  
 Executors提供了四種創建ExecutorService的方法,他們的使用場景如下:
  
  1. Executors.newFixedThreadPool() 
  
     創建一個定長的線程池,每提交一個任務就創建一個線程,直到達到池的最大長度,這時線程池會保持長度不再變化。
  
 當線程處於空閑狀態時,它們並不會被回收,除非線程池被關閉。當所有的線程都處於活動狀態時,新任務都會處於等待狀態,直到有線程空閑出來。
  
 只有核心線程並且不會被回收,能夠更加快速的響應外界的請求。
  
  2. Executors.newCachedThreadPool() 
  
     創建一個可緩存的線程池,如果當前線程池的長度超過了處理的需要時,它可以靈活的回收空閑的線程,當需要增加時,它可以靈活的添加新的線程,而不會對池的長度作任何限制
  
     線程數量不定的線程池,只有非核心線程,最大線程數為 Integer.MAX_VALUE。當線程池中的線程都處於活動狀態時,線程池會創建新的線程來處理新任務,否則利用空閑的線程來處理新任務。線程池中的空閑線程具有超時機制,為 60s。
  
     任務隊列相當於一個空集合,導致任何任務都會立即被執行,適合執行大量耗時較少的任務。當整個線程池都處於限制狀態時,線程池中的線程都會超時而被停止。
  
  3. Executors.newScheledThreadPool() 
  
     創建一個定長的線程池,而且支持定時的以及周期性的任務執行,類似於Timer。
  
     非核心線程數沒有限制,並且非核心線程閑置的時候立即回收,主要用於執行定時任務和具有固定周期的重復任務。
  
  4. Executors.newSingleThreadExecutor() 
  
     創建一個單線程化的executor,它只創建唯一的worker線程來執行任務
  
     只有一個核心線程,保證所有的任務都在一個線程中順序執行,意義在於不需要處理線程同步的問題。
  
     一般用於執行後台耗時任務,當任務執行完成會自動停止;同時由於它是一個服務,優先順序要遠遠高於線程,更不容易被系統殺死,因此比較適合執行一些高優先順序的後台任務。
  
  使用步驟:創建IntentService的子類,重寫onHandleIntent方法,在onHandleIntent中執行耗時任務 
  
     原理:在源碼實現上,IntentService封裝了HandlerThread和Handler。onHandleIntent方法結束後會調用IntentService的stopSelf(int startId)方法嘗試停止服務。
  
     IntentService的內部是通過消息的方式請求HandlerThread執行任務,HandlerThread內部又是一種使用Handler的Thread,這就意味著IntentService和Looper一樣是順序執行後台任務的
  
 (HandlerThread:封裝了Handler + ThreadHandlerThread適合在有需要一個工作線程(非UI線程)+任務的等待隊列的形式,優點是不會有堵塞,減少了對性能的消耗,缺點是不能同時進行多個任務的處理,需要等待進行處理。處理效率低,可以當成一個輕量級的線程池來用)
Ⅶ Android面試 Handler機制
 Handler就是解決線程與線程間的通信。
   當我們在子線程處理耗時操作,耗時操作完成後我們需要更新UI的時候,這就是需要使用Handler來處理了,因為子線程不能更  新UI,Handler能讓我們容易的把任務切換回來它所在的線程。
   消息處理機制本質:一個線程開啟循環模式持續監聽並依次處理其他線程給它發的消息。
一個線程可以有多個Handler,通過new Handler的方式創建。
一個線程只能有一個Looper,通過Looper.perpare方法會創建一個Looper保存在ThreadLocal中,每個線程都有一個LocalThreadMap,會將Looper保存在對應線程中的LocalThreadMap,key為ThreadLocal,value為Looper。
內部類持有外部類的對象,handler持有activity的對象,當頁面activity關閉時,handler還在發送消息,handler持有activity的對象,導致handler不能及時被回收,所以造成內存泄漏。
因為當handler發送消息時,會有耗時操作,並且會利用線程中的looper和messageQueue進行消息發送,looper和messageQueue的生命周期是很長的,和application一樣,所以handler不容易被銷毀,所以造成內存泄漏。
解決方案有:
可以在子線程中創建Handler,我們需要調用Looper.perpare和Looper.loop方法。或者通過獲取主線程的looper來創建Handler。
應該調用Looper的quit方法,因為可以將looper中的messageQueue里的message都移除掉,並且將內存釋放。
通過synchronized鎖機制保證線程安全。
Message.obtain來創建Message。這樣會復用之前的Message的內存,不會頻繁的創建對象,導致內存抖動。
點擊按鈕的時候會發送消息到Handler,但是為了保證優先執行,會加一個標記非同步,同時會發送一個target為null的消息,這樣在使用消息隊列的next獲取消息的時候,如果發現消息的target為null,那麼會遍歷消息隊列將有非同步標記的消息獲取出來優先執行,執行完之後會將target為null的消息移除。(同步屏障)
更多內容戳這里(整理好的各種文集)
Ⅷ 安卓的handler裡面的postDelay函數能不能用於多線程
你在此文件的上方找到import列表,看看是不是有import android.os.Handler;這個,會不會是import錯誤的類。你這個文件顯示的內容不太全,無法判斷會不會是其他原因//要做的事情,這里再次調用此Runnable對象,以實現每兩秒實現兆譽笑一次的定時器操作3、使用PostDelayed方法,兩秒後調用此Runnable對象4、如果想要關閉此定族含時器,可以這樣操作你復制了這么多,意思是說可以在新線程中直接(注意,是『直接』,不是虛閉傳參,傳遞過來)使用UI線程中的handler變數?
