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 -versionjmapjstack等。
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 ListenerSignal DispatcherFinalizerReference 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
  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值