查看java执行的线程信息
应用程序的
并发线程数
取决于该进程相关联的处理器内核数
。
1 通过 Java Api 打印java中的线程
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class Demo1 {
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());
}
}
}
虽然我们只执行了一个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命令时启动这两个线程。
2 top命令查看进程中的线程数
2.1 top -Hp pid
top -Hp 840
2.2 cat /proc/pid/status | grep Thread
cat /proc/840/status | grep Thread
2.3 pstree -p pid
yum -y install psmisc
pstree -p 840
3 实例演练1
3.1 在Linux上运行以下简单java代码
public static void main(String[] args) throws InterruptedException {
while (true) {
Thread.sleep(3000);
System.out.println("main...");
}
}
3.2 查看该java进程的线程数
方法1:
方法2:
方法3:
可以看到该java进程包含了10个线程。为什么会有这么多线程呢?
3.3 使用jstack查看线程详情
jstack -l 2040
=====================================================
结果如下:
2024-03-31 21:52:09
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.281-b09 mixed mode):
"Attach Listener" #8 daemon prio=9 os_prio=0 tid=0x00007fca84001000 nid=0x849 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007fcaa80b9000 nid=0x800 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007fcaa80b6000 nid=0x7ff waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007fcaa80b4000 nid=0x7fe waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007fcaa80b2800 nid=0x7fd runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007fcaa807d800 nid=0x7fc in Object.wait() [0x00007fcaade3d000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000c7208ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000000c7208ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007fcaa8079000 nid=0x7fb in Object.wait() [0x00007fcaadf3d000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000c7206c00> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000c7206c00> (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=0x00007fcaa800b000 nid=0x7f9 waiting on condition [0x00007fcab0bfe000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.michael.book1.Demo1.main(Demo1.java:14)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=0 tid=0x00007fcaa806f000 nid=0x7fa runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007fcaa80bc000 nid=0x801 waiting on condition
JNI global references: 5
在thread dump中每个线程都有一个nid(十六进制),该进成共有20个nid(线程)。主要包括:
Attach Listener
、Signal Dispatcher
、Finalizer
、Reference Handler
:GC task thread
:gc线程;C1 CompilerThread
:C1即时编译线程;C2 CompilerThread
:C2即时编译线程;main
:用户线程;
4 实例演练2
4.1 在main方法中启动2个子线程代码
public class Demo1 {
public static void main(String[] args) throws Exception {
System.out.println("main...");
Thread t1 = new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
System.out.println("t1 " + Thread.currentThread().getName() + "...");
} catch (Exception e) {
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
System.out.println("t2 " + Thread.currentThread().getName() + "...");
} catch (Exception e) {
}
}
});
t1.start();
t2.start();
}
}
可以看到我们的代码一共起了有3个线程。
4.2 命令查看线程信息
top -Hp 2193
pstree -p 2193
cat /proc/2193/status | grep Thread
可以看到一共有13个线程,比之前的单线程程序多了两个我们自定义的线程Thread-0,Thread-1。使用jstack查看可以发现多了如下两个线程信息:
2024-03-31 22:05:52
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.281-b09 mixed mode):
"Attach Listener" #11 daemon prio=9 os_prio=0 tid=0x00007f611c001000 nid=0x8bb waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"DestroyJavaVM" #10 prio=5 os_prio=0 tid=0x00007f614000b000 nid=0x892 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Thread-1" #9 prio=5 os_prio=0 tid=0x00007f6140117000 nid=0x89c waiting on condition [0x00007f6144de6000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.michael.book1.Demo1.lambda$main$1(Demo1.java:22)
at org.michael.book1.Demo1$$Lambda$2/245257410.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Thread-0" #8 prio=5 os_prio=0 tid=0x00007f6140115800 nid=0x89b waiting on condition [0x00007f6144ee6000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.michael.book1.Demo1.lambda$main$0(Demo1.java:11)
at org.michael.book1.Demo1$$Lambda$1/1044036744.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007f61400b9000 nid=0x899 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f61400b6000 nid=0x898 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f61400b4000 nid=0x897 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f61400b2800 nid=0x896 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f614007d800 nid=0x895 in Object.wait() [0x00007f614553e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000c7208ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000000c7208ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f6140079000 nid=0x894 in Object.wait() [0x00007f614563e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000c7206c00> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000c7206c00> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=0 tid=0x00007f614006f000 nid=0x893 runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007f61400bc000 nid=0x89a waiting on condition
JNI global references: 310