如何查看和排查一个进程中占用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
【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】