如何查看和排查一个进程中占用CPU比较高的线程

  今天想复现一下如何排查一个进程中比较高的线程。

对于如下代码:

import java.util.concurrent.CountDownLatch;

public class PlainTest {

    public static void main(String[] args) throws Exception {
        CountDownLatch countDownLatch = new CountDownLatch(1);

        Thread t1 = new Thread(() -> {
            int x = 5;
            while (true) {
                System.out.println(5 / 5);
            }
        });
        t1.setName("calc-t");
        t1.start();

        Thread t2 = new Thread(() -> {
            System.out.println(5 / 5);
        });
        t2.setName("calc-t2");
        t2.start();

        countDownLatch.await();
    }

}

1. linux 环境下进行测试

  这里基于docker 进行测试。

1. 进行编译

2. java PlainTest 跑起来程序

3. 新开一个docker 窗口进入容器

qiaoliqiang@A022296-NC01 MINGW64 ~
$ docker exec -it f7a07a1ddf3a bash

4. top 查看进程信息

top 打出的信息如下

top - 11:24:13 up 9 days, 12:40,  0 users,  load average: 1.12, 1.59, 1.48
Tasks:   5 total,   1 running,   4 sleeping,   0 stopped,   0 zombie
%Cpu(s): 13.3 us, 80.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  6.7 si,  0.0 st
KiB Mem :  1019768 total,    79568 free,   825352 used,   114848 buff/cache
KiB Swap:  1154060 total,       16 free,  1154044 used.    55000 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
   44 root      20   0 2142812  33608  15084 S 33.3  3.3   0:05.73 java
    1 root      20   0   11788   2612   2344 S  0.0  0.3   0:00.05 bash
   14 root      20   0   11788   2872   2488 S  0.0  0.3   0:00.04 bash
   56 root      20   0   11788   2820   2548 S  0.0  0.3   0:00.03 bash
   68 root      20   0   51916   3436   2960 R  0.0  0.3   0:00.00 top

5. 查看进程内部的线程信息

top -H -p pid 查看线程的线程ID与CPU占用情况  (也可以直接top 之后按H转换成线程模式)

例如,上面pid是44,结果如下:

top - 11:28:58 up 9 days, 12:45,  0 users,  load average: 2.67, 2.25, 1.80
Threads:  11 total,   1 running,  10 sleeping,   0 stopped,   0 zombie
%Cpu(s): 34.6 us, 65.4 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1019768 total,    76092 free,   824252 used,   119424 buff/cache
KiB Swap:  1154060 total,       68 free,  1153992 used.    53804 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
   54 root      20   0 2142812  33608  15084 R 43.9  3.3   1:57.24 java
   44 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.00 java
   45 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.15 java
   46 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.20 java
   47 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.00 java
   48 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.00 java
   49 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.00 java
   50 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.26 java
   51 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.09 java
   52 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.00 java
   53 root      20   0 2142812  33608  15084 S  0.0  3.3   0:00.16 java

然后jstack pid 查看线程信息:

[root@f7a07a1ddf3a /]# jstack -l 44
2021-06-26 11:31:30
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):

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

   Locked ownable synchronizers:
        - None

"calc-t" #8 prio=5 os_prio=0 tid=0x00007f1258103800 nid=0x36 runnable [0x00007f125d906000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileOutputStream.writeBytes(Native Method)
        at java.io.FileOutputStream.write(FileOutputStream.java:326)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        - locked <0x00000000f5978ee0> (a java.io.BufferedOutputStream)
        at java.io.PrintStream.write(PrintStream.java:482)
        - locked <0x00000000f596b158> (a java.io.PrintStream)
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
        at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
        - locked <0x00000000f596b118> (a java.io.OutputStreamWriter)
        at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
        at java.io.PrintStream.write(PrintStream.java:527)
        - eliminated <0x00000000f596b158> (a java.io.PrintStream)
        at java.io.PrintStream.print(PrintStream.java:597)
        at java.io.PrintStream.println(PrintStream.java:736)
        - locked <0x00000000f596b158> (a java.io.PrintStream)
        at PlainTest.lambda$main$0(PlainTest.java:12)
        at PlainTest$$Lambda$1/531885035.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
        - None

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

   Locked ownable synchronizers:
        - None

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

   Locked ownable synchronizers:
        - None

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

   Locked ownable synchronizers:
        - None

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

   Locked ownable synchronizers:
        - None

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f1258079000 nid=0x30 in Object.wait() [0x00007f125df0c000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000f596b9b8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x00000000f596b9b8> (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=0x00007f1258074800 nid=0x2f in Object.wait() [0x00007f125e00d000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000f596bb70> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000f596bb70> (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=0x00007f1258008800 nid=0x2d waiting on condition [0x00007f1261965000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000f596bb90> (a java.util.concurrent.CountDownLatch$Sync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
        at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
        at PlainTest.main(PlainTest.java:24)

   Locked ownable synchronizers:
        - None

"VM Thread" os_prio=0 tid=0x00007f125806d000 nid=0x2e runnable

"VM Periodic Task Thread" os_prio=0 tid=0x00007f12580b5800 nid=0x35 waiting on condition

JNI global references: 206

补充:

tid, Java memory address of its internal Thread control structure.    

nid, native thread id. 每一个nid对应于linux下的一个tid, 即lwp  (light weight process, or thread).

  

tid 最大的是54, 转换成十六进制就是  nid=0x36。  所以可以看到是calc-t  线程

2. windows 下面进行查看

 windows 下面可以用jvisualvm 进行查看

 补充: linux 下面查看占用端口的进程以及程序、程序所在的目录

(1) 查找进程

查看端口占用情况

netstat -ntpl | grep 9982

-t 查看tcp 端口

-l listening

--program|-p 显示建立相关链接的程序名

-n 拒绝显示别名,能显示数字的全部转化成数字。

(2) 找到进程号之后到 /proc 目录下会有进程ID,然后进入到进程ID目录,查看cwd 即可

[root@xxx 28493]# pwd
/proc/28493
[root@xxx 28493]# ll | grep cwd

或者直接 ll cwd
(3) 也可以在/proc/pid 目录下查看exe 来查看可执行文件所在的目录

[root@xxx 8080]# ll exe
lrwxrwxrwx 1 root root 0 6月 28 11:28 exe -> /usr/sbin/nginx
【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】
原文地址:https://www.cnblogs.com/qlqwjy/p/14938853.html