查看java线程

我们知道java线程使用的是底层操作系统"轻量级线程"+"内核线程"的1:1模型,那么我们如何查看一个运行的java进程中线程数呢?

1、linux上查看进程中线程数:

主要有以下三种方法:

1)top -Hp pid

$ top -Hp 12121
top - 13:37:23 up 223 days, 18:41,  2 users,  load average: 0.01, 0.02, 0.05
Threads:  20 total,   0 running,  20 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.1 us,  0.2 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16267876 total,   549064 free,  3220720 used, 12498092 buff/cache
KiB Swap:  2097148 total,  2034684 free,    62464 used. 11924764 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                  
12121 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12122 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.10 java                                     
12123 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12124 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12125 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12126 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12127 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12128 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12129 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12130 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12131 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12132 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12133 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12134 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12135 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12136 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12137 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12138 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12139 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12140 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.03 java    

2)cat /proc/pid/status | grep Thread

$ cat /proc/12121/status | grep Thread
Threads: 20

3)pstree -p pid:

$ pstree -p 12121
java(12121)─┬─{java}(12122)
            ├─{java}(12123)
            ├─{java}(12124)
            ├─{java}(12125)
            ├─{java}(12126)
            ├─{java}(12127)
            ├─{java}(12128)
            ├─{java}(12129)
            ├─{java}(12130)
            ├─{java}(12131)
            ├─{java}(12132)
            ├─{java}(12133)
            ├─{java}(12134)
            ├─{java}(12135)
            ├─{java}(12136)
            ├─{java}(12137)
            ├─{java}(12138)
            ├─{java}(12139)
            └─{java}(12140)

注:上述三种方法得到的结果都是一致的。

2、通过java api打印java中的线程:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

public class Test1 {
	public static void main(String[] args) {
		ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
		ThreadInfo[] threadInfo = threadBean.dumpAllThreads(false, false);
		for(ThreadInfo info : threadInfo){
            System.out.println(info.getThreadId() + "--" + info.getThreadName() +"--"+ info.getThreadState().name());
        }
	}
}

输出结果:

4--Signal Dispatcher--RUNNABLE

3--Finalizer--WAITING

2--Reference Handler--WAITING

1--main--RUNNABLE

说明:虽然我们写了一个main函数的单线程程序,但是JVM会启动一些额外的线程,主要包括:

  • Attach Listener 线程:负责接收外部JVM的命令,而对该命令进行执行的,并且把结果返回给发送者。如常用的命令:java -version、jmap、jstack等
  • Signal Dispatcher 线程:Attach Listener线程接收到命令后,会交给Signal Dispatcher线程去进行分发到各个不同的模块处理命令,并且返回处理结果
  • Finalizer 线程:在垃圾回收之前执行“对象完成”的Java系统线程
  • Reference Handler  线程:处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题

注意:Attach Listener、Signal Dispatcher线程在jvm启动的时候若没有初始化,那么则会在用户第一次执行jvm命令时启动这两个线程。

3、实战示例:

1)我们写一个main线程的(单线程)程序:

public class Test2 {
	public static void main(String[] args) throws Exception {
		while(true) {
			Thread.sleep(2000);
    		System.out.println("main...");
		}
	}
}

2)运行后,使用上面的方法查看该java进程的线程数:

$ top -Hp 12121
top - 13:37:23 up 223 days, 18:41,  2 users,  load average: 0.01, 0.02, 0.05
Threads:  20 total,   0 running,  20 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.1 us,  0.2 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16267876 total,   549064 free,  3220720 used, 12498092 buff/cache
KiB Swap:  2097148 total,  2034684 free,    62464 used. 11924764 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                  
12121 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12122 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.10 java                                     
12123 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12124 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12125 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12126 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12127 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12128 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12129 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12130 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12131 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12132 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12133 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12134 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12135 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12136 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12137 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12138 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12139 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.00 java                                     
12140 root      20   0 6963564  26104  10532 S  0.0  0.2   0:00.03 java    

可以看到该java进程包含了20个线程(使用另外的两种方法得到同样的结果)。这里有个问题,为什么会有这么多线程呢?

3)使用jstack查看线程详情:

$ jstack -l 12121
2020-02-16 13:39:26
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode):

"Attach Listener" #10 daemon prio=9 os_prio=0 tid=0x00002b9ad4001000 nid=0x3c78 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00002b9a800d2000 nid=0x2f6b runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00002b9a800c7000 nid=0x2f6a waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00002b9a800c4800 nid=0x2f69 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00002b9a800c3000 nid=0x2f68 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00002b9a800c0000 nid=0x2f67 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00002b9a800be800 nid=0x2f66 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00002b9a8008b800 nid=0x2f65 in Object.wait() [0x00002b9abd8be000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x000000076d408ec8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
	- locked <0x000000076d408ec8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

   Locked ownable synchronizers:
	- None

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00002b9a80086800 nid=0x2f64 in Object.wait() [0x00002b9abd7bd000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x000000076d406b68> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:502)
	at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
	- locked <0x000000076d406b68> (a java.lang.ref.Reference$Lock)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

   Locked ownable synchronizers:
	- None

"main" #1 prio=5 os_prio=0 tid=0x00002b9a80008800 nid=0x2f5a waiting on condition [0x00002b9a7b9c6000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at Test2.main(Test2.java:5)

   Locked ownable synchronizers:
	- None

"VM Thread" os_prio=0 tid=0x00002b9a8007f000 nid=0x2f63 runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00002b9a8001d800 nid=0x2f5b runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00002b9a8001f800 nid=0x2f5c runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00002b9a80021000 nid=0x2f5d runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00002b9a80023000 nid=0x2f5e runnable 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00002b9a80025000 nid=0x2f5f runnable 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00002b9a80026800 nid=0x2f60 runnable 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00002b9a80028800 nid=0x2f61 runnable 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00002b9a8002a800 nid=0x2f62 runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00002b9a800d5000 nid=0x2f6c waiting on condition 

JNI global references: 6

在thread dump中每个线程都有一个nid(十六进制),该进成共有20个nid(线程)。主要包括:

  • Attach Listener、Signal Dispatcher、Finalizer、Reference Handler
  • GC task thread:gc线程
  • C1 CompilerThread:C1即时编译线程;
  • C2 CompilerThread:C2即时编译线程;
  • main:用户线程

4)修改java代码,添加一个线程:

public class Test {

	public static void main(String[] args) throws Exception {
		System.out.println("main...");

		
		new Thread() {
			public void run() {
				while(true) {
					try {
						Thread.sleep(1000);
						System.out.println("test1...");
					} catch(Exception e) {

					}
				}
			}
		}.start();
		new Thread() {
			public void run() {
				while(true) {
					try {
						Thread.sleep(1000);
						System.out.println("test2...");
					} catch(Exception e) {

					}
				}
			}
		}.start();
	}
}

一共起了有3个线程(算main线程)。接下来我们运行该程序,并使用top查看该进程中的线程数。

$ top -Hp 11444
top - 14:05:29 up 223 days, 19:09,  2 users,  load average: 0.00, 0.01, 0.05
Threads:  22 total,   0 running,  22 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.1 sy,  0.0 ni, 99.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16267876 total,   537252 free,  3222404 used, 12508220 buff/cache
KiB Swap:  2097148 total,  2034684 free,    62464 used. 11914756 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                  
11444 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11445 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.09 java                                     
11447 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11448 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11449 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11450 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11451 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11452 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11453 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11454 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11466 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11473 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11477 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11487 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11488 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11489 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11490 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11491 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11492 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11493 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11494 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java                                     
11495 root      20   0 7096692  26292  10624 S  0.0  0.2   0:00.00 java  

 

我们看到一共有22个线程,比之前的单线程程序多了两个我们自定义的线程。使用jstack查看可以发现多了如下两个线程信息:

"Thread-1" #11 prio=5 os_prio=0 tid=0x00002adca410a000 nid=0x2ce7 waiting on condition [0x00002adce1715000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at Test$2.run(Test.java:24)

   Locked ownable synchronizers:
	- None

"Thread-0" #10 prio=5 os_prio=0 tid=0x00002adca4108000 nid=0x2ce6 waiting on condition [0x00002adce1614000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at Test$1.run(Test.java:12)

   Locked ownable synchronizers:
	- None

 

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赶路人儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值