java线程监控实践

java线程监控实践

查看java执行的线程信息

1 通过 Java Api 打印java中的线程2 top命令查看进程中的线程数2.1 `top -Hp pid`2.2 `cat /proc/pid/status | grep Thread`2.3 `pstree -p pid`

3 实例演练13.1 在Linux上运行以下简单java代码3.2 查看该java进程的线程数3.3 使用jstack查看线程详情

4 实例演练24.1 在main方法中启动2个子线程代码4.2 命令查看线程信息

应用程序的并发线程数取决于该进程相关联的处理器内核数。

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

相关推荐