天天看點

java 多線程卡頓_Android開發高手課之卡頓優化

造成卡頓的原因最後都會反映到CPU時間上,可以把CPU時間分為兩種:系統時間和使用者時間。

使用者時間:執行使用者态應用程式代碼所消耗的時間

系統時間:執行核心态系統調用所消耗的時間,包括I/O、鎖、中斷以及其他系統調用的時間

CPU性能

擷取cpu核心數

cat /sys/devices/system/cpu/possible

擷取某個cpu的頻率

cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq

卡頓問題分析名額

檢視cpu使用情況

/proc/stat 擷取整個系統的CPU使用情況

/proc/[pid]/stat 擷取某個程序的CPU使用情況

常用指令

top 檢視哪個程序是CPU消耗大戶

vmstat 實時動态監視作業系統的虛拟記憶體和CPU活動

strace 跟蹤某個程序所有的系統調用

CPU飽和度

CPU飽和度反應的是線程排隊等待CPU的情況,就是CPU的負載情況。

CPU飽和度會跟應用的線程數有關,如果啟動的線程過多,容易導緻系統不停的切換執行的線程,把時間浪費在上下文切換,每一次CPU上下文切換都需要重新整理寄存器和計數器。

檢視CPU上下文切換次數

vmstat

/proc/[pid]/schedstat

nr_voluntary_switches: 主動上下文切換次數,因為線程無法擷取所需資源導緻的上下文切換,最普遍的是IO

nr_involuntary_switches: 被動上下文切換次數,線程被系統強制排程導緻上下文切換,例如大量線程在搶占CPU

se.statistics.iowait_count:IO等待的次數

se.statistics.iowait_sum:IO等待的時間

線程優先級

線程優先級會影響Android系統的排程政策,它主要是由nice和cgroup類型共同決定的,nice值越低,搶占cpu時間片的能力越強。

注意是否存在高優先級的線程空等低優先級線程,例如主線程等待某個背景線程的鎖

Android卡頓排查工具

TraceView

Nanoscope

//安裝nanoscope 指令

brew tap uber/nanoscope

brew install nanoscope

nanoscope隻工作在Nanoscope模拟器或者安裝Nanoscope系統的裝置上

nanosscope emulator

//開始追蹤adb連接配接的裝置

nanoscope start

限制:

需要自己刷ROM,并且目前隻支援Nexus 6P,或者采用其提供的x86架構的模拟器

預設隻支援主線程采集,其他線程需要代碼手動設定

systrace

Simpleperf

卡頓現場

java實作

獲得java線程狀态

通過Thread的getState方法可以擷取線程狀态。

WAITING、TIME_WAITING、BLOCKED都是需要特别注意的狀态。

BLOCKED:是線程正在等待擷取鎖

WAITING: 是線程正在等待其他線程的喚醒動作。當一個線程處于waiting狀态時,不僅會釋放CPU資源,還會将持有的object鎖也同時釋放。

獲得所有線程堆棧

通過Thread.getAllStackTraces()拿到所有線程的堆棧,7.0之後該方法不會傳回主線程的堆棧。

BackgroundHandler屬于低優先級的背景線程,也就是主線程等待低優先級的背景線程

本質上Java線程的狀态其實是Native線程的一種映射。

Java線程狀态

NEW:當線程被建立,還沒有調用start方法時,線程就處于NEW狀态

RUNNABLE:該狀态表示線程具備所有運作條件,在運作隊列中準備作業系統的排程,或者正在運作。

BLOCKED:線程正在等待擷取java對象的螢幕,即線程正在等待進入由synchronized保護的方法或者代碼塊。

WAITING:處在該線程的狀态,正在等待某個事件的發生,隻有特定的條件滿足,才能獲得執行機會。

TIMED_WAITING:線程調用了限時版本的API,正在等待時間流逝,處在該狀态的線程,如果特定的事件發生或者時間流逝完畢,都會回複運作

TERMINATED:線程執行完畢,執行run方法正常傳回,或者抛出了運作時異常而結束,線程都會停留在這個狀态。