译自国外的一个博客,有不准确的地方请见谅。先上个例子:
"Thread-10" prio=5 tid=8 NATIVE
| group="main" sCount=0 dsCount=0 obj=0xf5f77d60 self=0x9f8f248
| sysTid=22299 nice=0 sched=0/0 cgrp=[n/a] handle=-256476304
| schedstat=( 153358572 709218 48 ) utm=12 stm=4 core=8
at MyClass.printString(Native Method)
at MyClass$1.run(MyClass.java:15)
术语
首先先认识几个术语,因为 ”thread“ 有很多不同的含义必须先了解:
- Thread:代表 java.lang.Thread
- pthread:代表C库中一个本地 thread 的抽象
- native thread:代表由内核创建的响应 clone(2) 系统调用的东西
- Thread*:代表 在VM 中的包括所有上述内容的 C 结构体
- thread:代表一个 thread 的抽象表示
"Thread-10" prio=5 tid=8 NATIVE
首先是 thread 名,被包含在一对双引号里。如果你赋予了一个 Thread 构造函数名字,那么它就是你在这里所看到的。否则它会是一个在 Thread 中的 static 的 int 值, 也就是单调递增的一个 thread id,用来给每个 thread 一个唯一的名字。这些 thread id 在给定的 VM 中不会被重复使用(虽然理论上来说你可以用 int 去包装)。
接下来就是 thread 的优先级。这是 Thread 的优先级表示,与 getPriority
,setPriority 和 MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY等常数对应。
再接着就是 thread 的 thin lock 的 id,用 ”tid“ 表示。如果你很熟悉 Linux,它肯会使你困惑,因为它不是 gettid(2) 系统调用中的 tid,而是 VM 的锁实现所使用的一个整数。这些 id 来自一个很小的池,所以当线程创建和销毁的时候可以重复使用,而且都是比较小的整数。
最后的就是 thread 的状态。这些状态与 Thread 的线程状态非常相似,但是有所扩展。它们当然会随着版本改变。一般 Dalvik 使用以下的状态 (在vm/Thread.h 中的 enum ThreadStatus 中)。
/* these match up with JDWP values */
THREAD_ZOMBIE = 0, /* TERMINATED */
THREAD_RUNNING = 1, /* RUNNABLE or running now */
THREAD_TIMED_WAIT = 2, /* TIMED_WAITING in Object.wait() */
THREAD_MONITOR = 3, /* BLOCKED on a monitor */
THREAD_WAIT = 4, /* WAITING in Object.wait() */
/* non-JDWP states */
THREAD_INITIALIZING = 5, /* allocated, not yet running */
THREAD_STARTING = 6, /* started, not yet on thread list */
THREAD_NATIVE = 7, /* off in a JNI native method */
THREAD_VMWAIT = 8, /* waiting on a VM resource */
THREAD_SUSPENDED = 9, /* suspended, usually by GC or debugger */
-
ZOMBIE :一般你不会看到 ZOMBIE 状态,因为线程只有当被拆卸的时候才会是这个状态。
-
RUNNING:RUNNING 的描述有点不准确,通常使用的词是 ”RUNNABLE“,因为当前 thread 是否真正在 core 上被调度并不受 VM 的管理。
-
TIMED_WAIT:与 Object.wait(long, int) 对应。注意,Thread.sleep 和 Object.wait(long) 目前都代表它。
-
WAIT:表示通过 Object.wait() 的没有延迟的等待、
-
MONITOR:表示 thread 试图在 monitor 上同步而被阻塞,要么是因为一个同步代码块,要么是一个同步方法(或者理论上来说,在一个调用 JNIEnv:MonitorEnter 上)。
-
INITIALIZING ,STARTING:当前thread 启动的实现。作为一个app 开发者,你可能会将这两个状态一起看成”运行我的代码还为时过早“。
-
NATIVE:表示 thread 在一个本地方法中。
-
VMWAIT:表示 thread 正在试图获取一些对管理的代码不可见资源而被阻塞,例如一个内部锁(即一个 phtread_mutex)。
-
SUSPENDED:表示 thread 已经被告知停止运行并且正在等待被允许继续执行,尤其是作为一个 app 开发者,当有个 GC 在运行或者一个 debugger 连接的时候你会看见它。
本例中没有显示,但是一个 deamon thread 会有一个 ”daemon“ 在第一行的后面。
| group="main" sCount=0 dsCount=0 obj=0xf5f77d60 self=0x9f8f248
- group:线程所属 ThreadGroup 名,被双引号括起来。
- sCount (suspension count):是请求这个 thread 挂起的数量。
- dsCount:来自 debugger 的请求这个 thread 挂起的数量。
sCount 与 dsCount 两个整数都与线程挂起有关,分开记录这两个值是因为如果一个 debugger 断开连接,那么 sCount 则可以被正确地重置(因为可能会有非 debugger 的挂起请求,我们不能在一个 debugger 断开时仅仅重置 sCount 为 0)。
obj:Thread 的地址。
self:Thread* 的地址。除非将 gdb(1) 附加到正在运行的dalvikvm进程,否则这些地址都不可能对您有用。
| sysTid=22299 nice=0 sched=0/0 cgrp=[n/a] handle=-256476304
- sysTid:kernel 的 thread id。如果你在 /proc/pid/task/tid目录下你可以使用它。通常这是这行唯一有用的东西。
- nice:kernel 对于进程的 nice 值。这是作为 getpriority(2) 系统调用的返回值。
- sched:pthread 调度策略和优先级。作为pthread_getschedparam(3) 系统调用的返回值。
- cgrp:thread 调度组的名字,从 /proc 下对应的 cgroup 文件拉取。
- handle:pthread对应这个线程的 pthread_t。除非你使用 gdb(1),否则很少被使用。
| schedstat=( 153358572 709218 48 ) utm=12 stm=4 core=8
schedstat:schedstat 数据是从 /proc 下的每个进程的 schedstat 文件中拉取的。它的格式被记录在 Linux kernel 树中(Documentation/scheduler/sched-stats.txt)。
- time spent on the cpu
- time spent waiting on a runqueue
- # of timeslices run on this cpu
如果kernel 不支持的话,你会看见 ”schedstat=( 0 0 0 ) “.
- utm:user-mode jiffies
- stm:kernel-mode jiffies
这些字段对应着 /proc 下每个线程的 stat 文件中额 utime 和 stime 字段。这些数字通常不会单独使用,除了在看哪些应用占用了所有的CPU时间。
- core:芯片中 CPU 的数量。
源自 http://elliotth.blogspot.com/2012/08/how-to-read-dalvik-sigquit-output.html
网友评论