2019.5.30今日Android面試題 - 線程

線程

Android中還了解哪些方便線程切換的類?

技術點:線程通信

參考回答:對Handler進一步的封裝的幾個類:

  • AsyncTask:底層封裝了線程池和Handler,便於執行後臺任務以及在子線程中進行UI操作。
  • HandlerThread:一種具有消息循環的線程,其內部可使用Handler。
  • IntentService:是一種異步、會自動停止的服務,內部採用HandlerThread。

引申:更多是對消息機制的理解

AsyncTask相比Handler有什麼優點?不足呢?

技術點:AsyncTask、Handler

參考回答

  • Handler機制存在的問題:多任務同時執行時不易精確控制線程。
  • 引入AsyncTask的好處:創建異步任務更簡單,直接繼承它可方便實現後臺異步任務的執行和進度的回調更新UI,而無需編寫任務線程和Handler實例就能完成相同的任務。

使用AsyncTask需要注意什麼?

技術點:AsyncTask

參考回答

  • 不要直接調用onPreExecute()、doInBackground()、onProgressUpdate()、onPostExecute()和onCancelled()方法
  • 一個異步對象只能調用一次execute()方法
  • 引申:談談AsyncTask初始化、五個核心方法如何配合進而體現Handler的作用

AsyncTask中使用的線程池大小?

技術點:AsyncTask

參考回答:在AsyncTask內部實現有兩個線程池:

  • SerialExecutor:用於任務的排隊,默認是串行的線程池,在3.0以前核心線程數爲5、線程池大小爲128,而3.0以後變爲同一時間只能處理一個任務
  • THREAD_POOL_EXECUTOR:用於真正執行任務。

引申:談談對線程池的理解

 HandlerThread有什麼特點?

技術點:HandlerThread

參考回答:HandlerThread是一個線程類,它繼承自Thread。與普通Thread不同,HandlerThread具有消息循環的效果,這是因爲它內部HandlerThread.run()方法中有Looper,能通過Looper.prepare()來創建消息隊列,並通過Looper.loop()來開啓消息循環。

 快速實現子線程使用Handler

技術點:HandlerThread

思路:不同於之前手動在子線程創建Looper再構建Handler的想法,這裏從HandlerThread角度去快速實現在子線程使用Handler

參考回答:HandlerThread實現方法

  • 實例化一個HandlerThread對象,參數是該線程的名稱;
  • 通過 HandlerThread.start()開啓線程;
  • 實例化一個Handler並傳入HandlerThread中的looper對象,使得與HandlerThread綁定;
  • 利用Handler即可執行異步任務;
  • 當不需要HandlerThread時,通過HandlerThread.quit()/quitSafely()方法來終止線程的執行。

 IntentService的特點?

技術點:IntentService

思路:和普通線程和普通Service比較突出其特點

參考回答: 不同於線程,IntentService是服務,優先級比線程高,更不容易被系統殺死,因此較適合執行一些高優先級的後臺任務;不同於普通Service,IntentService可自動創建子線程來執行任務,且任務執行完畢後自動退出

 爲何不用bindService方式創建IntentService?

技術點:IntentService

思路:從底層實現出發

參考回答:IntentService的工作原理是,在IntentService的onCreate()裏會創建一個HandlerThread,並利用其內部的Looper實例化一個ServiceHandler對象;而這個ServiceHandler用於處理消息的handleMessage()方法會去調用IntentService的onHandleIntent(),這也是爲什麼可在該方法中處理後臺任務的邏輯;當有Intent任務請求時會把Intent封裝到Message,然後ServiceHandler會把消息發送出,而發送消息是在onStartCommand()完成的,只能通過startService()纔可走該生命週期方法,因此不能通過bindService創建IntentService。

 線程池的好處、原理、類型?

技術點:線程池

參考回答:

  • (1)線程池的好處:
    • 重用線程池中的線程,避免線程的創建和銷燬帶來的性能消耗;
    • 有效控制線程池的最大併發數,避免大量的線程之間因互相搶佔系統資源而導致阻塞現象;
    • 進行線程管理,提供定時/循環間隔執行等功能
  • (2)線程池的分類:
    • FixThreadPool:線程數量固定的線程池,所有線程都是核心線程,當線程空閒時不會被回收;能快速響應外界請求。
    • CachedThreadPool:線程數量不定的線程池(最大線程數爲Integer.MAX_VALUE),只有非核心線程,空閒線程有超時機制,超時回收;適合於執行大量的耗時較少的任務
    • ScheduledThreadPool:核心線程數量固定,非核心線程數量不定;可進行定時任務和固定週期的任務。
    • SingleThreadExecutor:只有一個核心線程,可確保所有的任務都在同一個線程中按順序執行;好處是無需處理線程同步問題。
  • (3)線程池的原理:實際上通過ThreadPoolExecutor並通過一系列參數來配置各種各樣的線程池,具體的參數有:
    • corePoolSize核心線程數:一般會在線程中一直存活
    • maximumPoolSize最大線程數:當活動線程數達到這個數值後,後續的任務將會被阻塞

keepAliveTime非核心線程超時時間:超過這個時長,閒置的非核心線程就會被回收

  • unit:用於指定keepAliveTime參數的時間單位
  • workQueue任務隊列:通過線程池的execute()方法提交的Runnable對象會存儲在這個參數中。
  • threadFactory:線程工廠,可創建新線程
  • handler:在線程池無法執行新任務時進行調度

 ThreadPoolExecutor的工作策略?

技術點:線程池

參考回答:ThreadPoolExecutor的默認工作策略

  • 若程池中的線程數量未達到核心線程數,則會直接啓動一個核心線程執行任務。
  • 若線程池中的線程數量已達到或者超過核心線程數量,則任務會被插入到任務列表等待執行。
    • 若任務無法插入到任務列表中,往往由於任務列表已滿,此時如果
      • 線程數量未達到線程池最大線程數,則會啓動一個非核心線程執行任務;
      • 線程數量已達到線程池規定的最大值,則拒絕執行此任務,ThreadPoolExecutor會調用RejectedExecutionHandler的rejectedExecution方法來通知調用者。

引申:ThreadPoolExecutor的拒絕策略

 什麼是ANR?什麼情況會出現ANR?如何避免?在不看代碼的情況下如何快速定位出現ANR問題所在?

技術點:ANR
參考回答

  • ANR(Application Not Responding,應用無響應):當操作在一段時間內系統無法處理時,會在系統層面會彈出ANR對話框
  • 產生ANR可能是因爲5s內無響應用戶輸入事件、10s內未結束BroadcastReceiver、20s內未結束Service
  • 想要避免ANR就不要在主線程做耗時操作,而是通過開子線程,方法比如繼承Thread或實現Runnable接口、使用AsyncTask、IntentService、HandlerThread等
  • 引申:快讀定位ANR方法:使用命令導出ANR日誌,並分析關鍵信息,詳見如何分析ANR

                                                              


                                                                                                                                  by .k

 

關注"編程v",每一天漲一點

STAY HUNGRY & STAY FOOLISH

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章