Android線程狀態(tài)

經(jīng)常在分析 ANR 問題的時候,需要對線程狀態(tài)了解得比較清楚,才能進一步分析問題萄喳。

線程狀態(tài)

java 的線程狀態(tài)定義在 Thread.State 中芬骄,如下:

public enum State {
    /**
    * Thread state for a thread which has not yet started.
    */
    NEW,
    
    /**
    * Thread state for a runnable thread.  A thread in the runnable
    * state is executing in the Java virtual machine but it may
    * be waiting for other resources from the operating system
    * such as processor.
    */
    RUNNABLE,
    
    /**
    * Thread state for a thread blocked waiting for a monitor lock.
    * A thread in the blocked state is waiting for a monitor lock
    * to enter a synchronized block/method or
    * reenter a synchronized block/method after calling
    * {@link Object#wait() Object.wait}.
    */
    BLOCKED,
    
    /**
    * Thread state for a waiting thread.
    * A thread is in the waiting state due to calling one of the
    * following methods:
    * <ul>
    *   <li>{@link Object#wait() Object.wait} with no timeout</li>
    *   <li>{@link #join() Thread.join} with no timeout</li>
    *   <li>{@link LockSupport#park() LockSupport.park}</li>
    * </ul>
    *
    * <p>A thread in the waiting state is waiting for another thread to
    * perform a particular action.
    *
    * For example, a thread that has called <tt>Object.wait()</tt>
    * on an object is waiting for another thread to call
    * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
    * that object. A thread that has called <tt>Thread.join()</tt>
    * is waiting for a specified thread to terminate.
    */
    WAITING,
    
    /**
    * Thread state for a waiting thread with a specified waiting time.
    * A thread is in the timed waiting state due to calling one of
    * the following methods with a specified positive waiting time:
    * <ul>
    *   <li>{@link #sleep Thread.sleep}</li>
    *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
    *   <li>{@link #join(long) Thread.join} with timeout</li>
    *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
    *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
    * </ul>
    */
    TIMED_WAITING,
    
    /**
    * Thread state for a terminated thread.
    * The thread has completed execution.
    */
    TERMINATED;
    }

其中猾愿,相關狀態(tài)如下:

狀態(tài) 說明
NEW 線程創(chuàng)建,但是還沒有start()
RUNNABLE 線程執(zhí)行或者在等待系統(tǒng)資源账阻,例如CPU資源
BLOCKED 線程在等待其它線程釋放一個鎖蒂秘,則會進入 Blocked 狀態(tài)。例如在等待一個同步代碼塊的鎖淘太,獲得鎖則進入 Runnable 狀態(tài)
WAITING 線程在等待一個其它線程喚醒它姻僧。可能是調用了 Object.wait(),Thread.join() ,LockSupport.part()
TIMED_WAITING 同上蒲牧,只不過方法換成了 Object.wait(timeOut) ,Thread.join(millis<br />) ,LockSupport.part(deadline<br />)
TERMINATED 線程銷毀

java 的線程狀態(tài)也是讀取 native 線程的狀態(tài)撇贺,如下:

//Thread.java
public State getState() {
        // get current thread state
        // Android-changed: Replace unused threadStatus field with started field.
        // Use Android specific nativeGetStatus() method. See comment on started field for more
        // information.
        // return sun.misc.VM.toThreadState(threadStatus);
        return State.values()[nativeGetStatus(started)];
    }
private native int nativeGetStatus(boolean hasBeenStarted);

對應的 jni 實現(xiàn),在 java_lang_Thread.cc 中:

static jint Thread_nativeGetStatus(JNIEnv* env, jobject java_thread, jboolean has_been_started) {
  // Ordinals from Java's Thread.State.
  const jint kJavaNew = 0;
  const jint kJavaRunnable = 1;
  const jint kJavaBlocked = 2;
  const jint kJavaWaiting = 3;
  const jint kJavaTimedWaiting = 4;
  const jint kJavaTerminated = 5;

  ScopedObjectAccess soa(env);
  ThreadState internal_thread_state =
      (has_been_started ? ThreadState::kTerminated : ThreadState::kStarting);
  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
  Thread* thread = Thread::FromManagedThread(soa, java_thread);
  if (thread != nullptr) {
    internal_thread_state = thread->GetState();
  }
  switch (internal_thread_state) {
    case ThreadState::kTerminated:                     return kJavaTerminated;
    case ThreadState::kRunnable:                       return kJavaRunnable;
    case ThreadState::kObsoleteRunnable:               break;  // Obsolete value.
    case ThreadState::kTimedWaiting:                   return kJavaTimedWaiting;
    case ThreadState::kSleeping:                       return kJavaTimedWaiting;
    case ThreadState::kBlocked:                        return kJavaBlocked;
    case ThreadState::kWaiting:                        return kJavaWaiting;
    case ThreadState::kStarting:                       return kJavaNew;
    case ThreadState::kNative:                         return kJavaRunnable;
    case ThreadState::kWaitingForTaskProcessor:        return kJavaWaiting;
    case ThreadState::kWaitingForLockInflation:        return kJavaWaiting;
    case ThreadState::kWaitingForGcToComplete:         return kJavaWaiting;
    case ThreadState::kWaitingPerformingGc:            return kJavaWaiting;
    case ThreadState::kWaitingForCheckPointsToRun:     return kJavaWaiting;
    case ThreadState::kWaitingForDebuggerSend:         return kJavaWaiting;
    case ThreadState::kWaitingForDebuggerToAttach:     return kJavaWaiting;
    case ThreadState::kWaitingInMainDebuggerLoop:      return kJavaWaiting;
    case ThreadState::kWaitingForDebuggerSuspension:   return kJavaWaiting;
    case ThreadState::kWaitingForDeoptimization:       return kJavaWaiting;
    case ThreadState::kWaitingForGetObjectsAllocated:  return kJavaWaiting;
    case ThreadState::kWaitingForJniOnLoad:            return kJavaWaiting;
    case ThreadState::kWaitingForSignalCatcherOutput:  return kJavaWaiting;
    case ThreadState::kWaitingInMainSignalCatcherLoop: return kJavaWaiting;
    case ThreadState::kWaitingForMethodTracingStart:   return kJavaWaiting;
    case ThreadState::kWaitingForVisitObjects:         return kJavaWaiting;
    case ThreadState::kWaitingWeakGcRootRead:          return kJavaRunnable;
    case ThreadState::kWaitingForGcThreadFlip:         return kJavaWaiting;
    case ThreadState::kNativeForAbort:                 return kJavaWaiting;
    case ThreadState::kSuspended:                      return kJavaRunnable;
    // Don't add a 'default' here so the compiler can spot incompatible enum changes.
  }
  LOG(ERROR) << "Unexpected thread state: " << internal_thread_state;
  return -1;  // Unreachable.
}

所以在 C++ 層中造成,對應的相關狀態(tài)如下:

enum class ThreadState : uint8_t {
    // `kRunnable` was previously 67 but it is now set to 0 so that we do not need to extract
    // flags from the thread's `state_and_flags` to check for any flag being set while Runnable.
    // Note: All atomic accesses for a location should use the same data size,
    // so the incorrect old approach of reading just 16 bits has been rewritten.
    
    //                                   Java
    //                                   Thread.State   JDWP state
    kTerminated = 66,                 // TERMINATED     TS_ZOMBIE    Thread.run has returned, but Thread* still around
    kRunnable = 0,                    // RUNNABLE       TS_RUNNING   runnable
    kObsoleteRunnable = 67,           // ---            ---          obsolete value
    kTimedWaiting = 68,               // TIMED_WAITING  TS_WAIT      in Object.wait() with a timeout
    kSleeping,                        // TIMED_WAITING  TS_SLEEPING  in Thread.sleep()
    kBlocked,                         // BLOCKED        TS_MONITOR   blocked on a monitor
    kWaiting,                         // WAITING        TS_WAIT      in Object.wait()
    kWaitingForLockInflation,         // WAITING        TS_WAIT      blocked inflating a thin-lock
    kWaitingForTaskProcessor,         // WAITING        TS_WAIT      blocked waiting for taskProcessor
    kWaitingForGcToComplete,          // WAITING        TS_WAIT      blocked waiting for GC
    kWaitingForCheckPointsToRun,      // WAITING        TS_WAIT      GC waiting for checkpoints to run
    kWaitingPerformingGc,             // WAITING        TS_WAIT      performing GC
    kWaitingForDebuggerSend,          // WAITING        TS_WAIT      blocked waiting for events to be sent
    kWaitingForDebuggerToAttach,      // WAITING        TS_WAIT      blocked waiting for debugger to attach
    kWaitingInMainDebuggerLoop,       // WAITING        TS_WAIT      blocking/reading/processing debugger events
    kWaitingForDebuggerSuspension,    // WAITING        TS_WAIT      waiting for debugger suspend all
    kWaitingForJniOnLoad,             // WAITING        TS_WAIT      waiting for execution of dlopen and JNI on load code
    kWaitingForSignalCatcherOutput,   // WAITING        TS_WAIT      waiting for signal catcher IO to complete
    kWaitingInMainSignalCatcherLoop,  // WAITING        TS_WAIT      blocking/reading/processing signals
    kWaitingForDeoptimization,        // WAITING        TS_WAIT      waiting for deoptimization suspend all
    kWaitingForMethodTracingStart,    // WAITING        TS_WAIT      waiting for method tracing to start
    kWaitingForVisitObjects,          // WAITING        TS_WAIT      waiting for visiting objects
    kWaitingForGetObjectsAllocated,   // WAITING        TS_WAIT      waiting for getting the number of allocated objects
    kWaitingWeakGcRootRead,           // WAITING        TS_WAIT      waiting on the GC to read a weak root
    kWaitingForGcThreadFlip,          // WAITING        TS_WAIT      waiting on the GC thread flip (CC collector) to finish
    kNativeForAbort,                  // WAITING        TS_WAIT      checking other threads are not run on abort.
    kStarting,                        // NEW            TS_WAIT      native thread started, not yet ready to run managed code
    kNative,                          // RUNNABLE       TS_RUNNING   running in a JNI native method
    kSuspended,                       // RUNNABLE       TS_RUNNING   suspended by GC or debugger
};

可以看到 C++ 里面的線程狀態(tài)會有更多的細節(jié)显熏。其中,包括 kNative 表示正在執(zhí)行 native 方法晒屎。
<a name="yFpdf"></a>

ANR 日志中線程狀態(tài)說明

類似的 ANR 日志如下:

"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x75af8d38 self=0xefe71e00
  | sysTid=5423 nice=-10 cgrp=default sched=0/0 handle=0xf0273dc0
  | state=S schedstat=( 61207235540 31084517122 178273 ) utm=4704 stm=1416 core=1 HZ=100
  | stack=0xff039000-0xff03b000 stackSize=8192KB
  | held mutexes=
  kernel: (couldn't read /proc/self/task/5423/stack)
  native: #00 pc 00052188  /apex/com.android.runtime/lib/bionic/libc.so (syscall+28)
  native: #01 pc 0005750f  /apex/com.android.runtime/lib/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+90)
  native: #02 pc 000a07f3  /apex/com.android.runtime/lib/bionic/libc.so (pthread_cond_wait+32)
  native: #03 pc 0006949b  /data/app/com.starify.ola.android-62F7MEKjVCxvF8JrKvQgEw==/lib/arm/libalivc_conan.so (std::__ndk1::condition_variable::wait(std::__ndk1::unique_lock<std::__ndk1::mutex>&)+26)
  native: #04 pc 00069c3d  /data/app/com.starify.ola.android-62F7MEKjVCxvF8JrKvQgEw==/lib/arm/libalivc_conan.so (std::__ndk1::__assoc_sub_state::__sub_wait(std::__ndk1::unique_lock<std::__ndk1::mutex>&)+32)
  native: #05 pc 00069bb3  /data/app/com.starify.ola.android-62F7MEKjVCxvF8JrKvQgEw==/lib/arm/libalivc_conan.so (std::__ndk1::__assoc_sub_state::copy()+38)
  native: #06 pc 00069dd7  /data/app/com.starify.ola.android-62F7MEKjVCxvF8JrKvQgEw==/lib/arm/libalivc_conan.so (std::__ndk1::future<void>::get()+12)
  native: #07 pc 0029499b  /data/app/com.starify.ola.android-62F7MEKjVCxvF8JrKvQgEw==/lib/arm/libugsv.so (???)
  native: #08 pc 0009786b  /data/app/com.starify.ola.android-62F7MEKjVCxvF8JrKvQgEw==/lib/arm/libugsv.so (???)
  native: #09 pc 0008f6bd  /data/app/com.starify.ola.android-62F7MEKjVCxvF8JrKvQgEw==/lib/arm/libugsv.so (???)
  native: #10 pc 0009122b  /data/app/com.starify.ola.android-62F7MEKjVCxvF8JrKvQgEw==/lib/arm/libugsv.so (???)

其中喘蟆,第一行 "main" prio=5 tid=1 Native,表示當前線程的狀態(tài)是 Native鼓鲁。那么在 ANR 日志中蕴轨,線程的狀態(tài)細分如下:

java Thread 的狀態(tài) C++ 層Thread 狀態(tài) 說明
NEW INITIALIZING 新建,正在分配資源
NEW STARING 新建骇吭,正在啟動
RUNNABLE RUNING/RUNNABLE 線程創(chuàng)建或者正在運行
RUNNABLE NATIVE 正在執(zhí)行 JNI 方法
RUNNABLE SUSPENDED 現(xiàn)在掛起橙弱,一般是GC導致
BLOCKED MOINITOR 線程阻塞,等待其它線程釋放對象鎖
WAITING WAIT 執(zhí)行了無超時參數(shù)的 wait() 等方法
WAITING VMWAIT 正在等待 VM 資源
TERMINATED ZOMBIE 線程銷毀

其中,我們主要關心的狀態(tài)是 MOINITOR棘脐,WAIT斜筐,如果主線程是這個狀態(tài),那么 ANR 的原因就是主線程被阻塞或者在等待子線程釋放鎖蛀缝。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末顷链,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子屈梁,更是在濱河造成了極大的恐慌嗤练,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件在讶,死亡現(xiàn)場離奇詭異煞抬,居然都是意外死亡,警方通過查閱死者的電腦和手機构哺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門革答,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人遮婶,你說我怎么就攤上這事蝗碎『浚” “怎么了旗扑?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長慈省。 經(jīng)常有香客問我臀防,道長,這世上最難降的妖魔是什么边败? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任袱衷,我火速辦了婚禮,結果婚禮上笑窜,老公的妹妹穿的比我還像新娘致燥。我一直安慰自己,他們只是感情好排截,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布嫌蚤。 她就那樣靜靜地躺著,像睡著了一般断傲。 火紅的嫁衣襯著肌膚如雪脱吱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天认罩,我揣著相機與錄音箱蝠,去河邊找鬼。 笑死,一個胖子當著我的面吹牛宦搬,可吹牛的內容都是我干的牙瓢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼间校,長吁一口氣:“原來是場噩夢啊……” “哼一罩!你這毒婦竟也來了?” 一聲冷哼從身側響起撇簿,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤聂渊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后四瘫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體汉嗽,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年找蜜,在試婚紗的時候發(fā)現(xiàn)自己被綠了饼暑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡洗做,死狀恐怖弓叛,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情诚纸,我是刑警寧澤撰筷,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站畦徘,受9級特大地震影響毕籽,放射性物質發(fā)生泄漏。R本人自食惡果不足惜井辆,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一关筒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杯缺,春花似錦蒸播、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至匾鸥,卻和暖如春蜡塌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勿负。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工馏艾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留劳曹,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓琅摩,卻偏偏與公主長得像铁孵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子房资,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內容