3

浅析Android中的线程状态

 3 years ago
source link: http://yuanfentiank789.github.io/2017/09/15/%E6%B5%85%E6%9E%90Android%E4%B8%AD%E7%9A%84%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
浅析Android中的线程状态 - JackPeng博客

在分析ANR问题时,第一步就是把/data/anr/traces.txt这个文件adb pull出来分析, 它记录了手机发生ANR时, 各个进程里的所有线程在当时的状态. 典型的情况是:

----- pid 9644 at 2015-12-18 18:06:11 -----
Cmd line: com.tencent.androidqqmail:Push

DALVIK THREADS:
(mutexes: tll=0 tsl=0 tscl=0 ghl=0)

"main" prio=5 tid=1 MONITOR
  | group="main" sCount=1 dsCount=0 obj=0x41e42b50 self=0x41e321f0
  | sysTid=9644 nice=0 sched=0/0 cgrp=apps handle=1074578908
  | state=S schedstat=( 211181635 61197479253 655 ) utm=13 stm=8 core=0
  at com.tencent.qqmail.utilities.qmnetwork.service.QMPushService.onStartCommand(SourceFile:~288)
  - waiting to lock <0x421809c0> (a com.tencent.qqmail.utilities.qmnetwork.service.QMPushService) held by tid=15 (Thread-2740)
  at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2679)
  at android.app.ActivityThread.access$1900(ActivityThread.java:149)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1343)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:213)
  at android.app.ActivityThread.main(ActivityThread.java:5092)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:511)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:564)
  at dalvik.system.NativeStart.main(Native Method)

"Timer-0" daemon prio=5 tid=23 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 obj=0x42313248 self=0x72be2018
  | sysTid=9693 nice=0 sched=0/0 cgrp=apps handle=1074262912
  | state=S schedstat=( 178436271 61426971433 856 ) utm=7 stm=10 core=0
  at java.lang.Object.wait(Native Method)
  - waiting on <0x42313248> (a java.util.Timer$TimerImpl)
  at java.lang.Object.wait(Object.java:401)
  at java.util.Timer$TimerImpl.run(Timer.java:238)

"QMThreadPool #3" daemon prio=3 tid=22 WAIT
  | group="main" sCount=1 dsCount=0 obj=0x42310418 self=0x700656f8
  | sysTid=9692 nice=13 sched=0/0 cgrp=apps/bg_non_interactive handle=1924222744
  | state=S schedstat=( 25787332 62892517091 453 ) utm=0 stm=2 core=0
  at java.lang.Object.wait(Native Method)
  - waiting on <0x42310538> (a java.lang.VMThread) held by tid=22 (QMThreadPool #3)
  at java.lang.Thread.parkFor(Thread.java:1231)
  at sun.misc.Unsafe.park(Unsafe.java:323)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2019)
  at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)
  at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
  at java.lang.Thread.run(Thread.java:856)
"WifiManager" prio=5 tid=20 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x42213ba0 self=0x7363b008
  | sysTid=9686 nice=0 sched=0/0 cgrp=apps handle=1923316488
  | state=S schedstat=( 41564937 61108032226 478 ) utm=1 stm=3 core=0
  #00  pc 00017fe8  /system/lib/libc.so (epoll_wait+12)
  #01  pc 00014b29  /system/lib/libutils.so (android::Looper::pollInner(int)+96)
  #02  pc 00014d91  /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+104)
  #03  pc 0006725b  /system/lib/libandroid_runtime.so (android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22)
  #04  pc 00020050  /system/lib/libdvm.so (dvmPlatformInvoke+112)
  #05  pc 0004f8d1  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+396)
  #06  pc 000294e0  /system/lib/libdvm.so
  #07  pc 0002d7a0  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
  #08  pc 000620ed  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
  #09  pc 00062117  /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20)
  #10  pc 00056c8f  /system/lib/libdvm.so
  #11  pc 0000e4b8  /system/lib/libc.so (__thread_entry+72)
  #12  pc 0000dba4  /system/lib/libc.so (pthread_create+160)
  at android.os.MessageQueue.nativePollOnce(Native Method)
  at android.os.MessageQueue.next(MessageQueue.java:125)
  at android.os.Looper.loop(Looper.java:197)
  at android.os.HandlerThread.run(HandlerThread.java:60)
"Signal Catcher" daemon prio=5 tid=3 RUNNABLE
  | group="system" sCount=0 dsCount=0 obj=0x4211bac8 self=0x7306f9e8
  | sysTid=9649 nice=0 sched=0/0 cgrp=apps handle=1074354432
  | state=R schedstat=( 35980238 61091796864 464 ) utm=0 stm=3 core=0
  at dalvik.system.NativeStart.run(Native Method)


这里的MONITOR,NATIVE等线程状态很是让我们迷惑, 因为我们学习到的java thread的6种线程状态并不包含它们. java的6种线程状态定义在/java/lang/Thread.java中:

//Thread.java
public class Thread implements Runnable {
    ...
    public enum State {
        /**
         * The thread has been created, but has never been started.
         */
        NEW,
        /**
         * The thread may be run.
         */
        RUNNABLE,
        /**
         * The thread is blocked and waiting for a lock.
         */
        BLOCKED,
        /**
         * The thread is waiting.
         */
        WAITING,
        /**
         * The thread is waiting for a specified amount of time.
         */
        TIMED_WAITING,
        /**
         * The thread has been terminated.
         */
        TERMINATED
    }
    ...
}

我们却发现这里的MONITOR并不在这6种状态中, 那么MONITOR到底代表的是什么意思呢? 就需要我们深入源码去找答案了. "main" prio=5 tid=1 MONITOR 在VMThread.java中, 可以看到下面的代码, native thread有10种状态, 对应着java thread的6种状态.

//VMThread.java
    /**
     * Holds a mapping from native Thread statuses to Java one. Required for
     * translating back the result of getStatus().
     */
    static final Thread.State[] STATE_MAP = new Thread.State[] {
        Thread.State.TERMINATED,     // ZOMBIE
        Thread.State.RUNNABLE,       // RUNNING
        Thread.State.TIMED_WAITING,  // TIMED_WAIT
        Thread.State.BLOCKED,        // MONITOR
        Thread.State.WAITING,        // WAIT
        Thread.State.NEW,            // INITIALIZING
        Thread.State.NEW,            // STARTING
        Thread.State.RUNNABLE,       // NATIVE
        Thread.State.WAITING,        // VMWAIT
        Thread.State.RUNNABLE        // SUSPENDED
    };


这段代码就给出了答案, traces.txt文件中的MONITOR状态就对应着java的BLOCKED状态, 也就是”The thread is blocked and waiting for a lock.” 在之前的文章中, 已经分析了android thread的底层实现其实就是linux下的pthread. 我们再看一下native层的Thread.cpp, 有这段代码: http://osxr.org/android/source/dalvik/vm/Thread.cpp

const char* dvmGetThreadStatusStr(ThreadStatus status)
{
    switch (status) {
        case THREAD_ZOMBIE:         return "ZOMBIE";
        case THREAD_RUNNING:        return "RUNNABLE";
        case THREAD_TIMED_WAIT:     return "TIMED_WAIT";
        case THREAD_MONITOR:        return "MONITOR";
        case THREAD_WAIT:           return "WAIT";
        case THREAD_INITIALIZING:   return "INITIALIZING";
        case THREAD_STARTING:       return "STARTING";
        case THREAD_NATIVE:         return "NATIVE";
        case THREAD_VMWAIT:         return "VMWAIT";
        case THREAD_SUSPENDED:      return "SUSPENDED";
        default:                    return "UNKNOWN";
    }
}


实际上, 写入traces.txt中的线程状态值就是这个函数返回的字符串. 所以我们就知道了如下的事实:

"main" prio=5 tid=1 MONITOR  其实就是java中的BLOCKED状态.
"Timer-0" daemon prio=5 tid=23 TIMED_WAIT 其实就是java中的TIMED_WAITING状态
"QMThreadPool #3" daemon prio=3 tid=22 WAIT 其实就是java中的WAITING状态
"WifiManager" prio=5 tid=20 NATIVE 其实就是java中的RUNNABLE状态
"Signal Catcher" daemon prio=5 tid=3 RUNNABLE 其实就是java中的RUNNABLE状态


到这里, 我们也同样理解了DDMS中各个线程状态的含义. 1240



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK