線程
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