您的当前位置:首页正文

排查CPU使用过高问题操作详解,三招助你找出问题

2024-12-01 来源:个人技术集锦

背景

对于系统运行越来卡顿,响应越来越慢的问题,绝大多数情况是程序本身问题造成的,掌握相关问题的排查和定位尤其重要。

现象

使用top命名查看目前服务所占cpu情况:

通过信息,可以看到有个进程占用CPU过高,接下来排查系统代码中哪些逻辑导致CPU过高。

步骤

第一步:通过ps命令查看这个程序的线程信息。

执行命令:ps -mp 27291-o THREAD,tid,time

属性介绍:tid代码线程ID,time代表这个线程的已运行时间,27291为对应pid的值。

如图可以看到这个进程中有1个线程的CPU占用率很高,达到了98.5%,并且它们目前也运行了44分钟了,对应TID为:27909

第二步:将TID(代码线程ID)转为16进制

因为jvm运行信息都是16进制,所以,这里需要将十进制转为16进制。

执行命令: printf"%x\n" 27909

第三步:jstack查看进程信息

执行命令:jstack27291 | grep 6d05 -A 30

内容介绍:27291 为pid进程,6d05 为需要查看的线程tid

输出信息有较为明显的的代码信息。

根据上面输出信息可以很快定位到本地代码存在的问题。

补充:

线程的Thread状态(java.lang.Thread.State)内容说明:

一个Thread对象可以有多个状态,在java.lang.Thread.State中,总共定义六种状态:

1、NEW

线程刚刚被创建,也就是已经new过了,但是还没有调用start()方法,jstack命令不会列出处于此状态的线程信息

2、RUNNABLE

RUNNABLE这个名字很具有欺骗性,很容易让人误以为处于这个状态的线程正在运行。事实上,这个状态只是表示,线程是可运行的。我们已经无数次提到过,一个单核CPU在同一时刻,只能运行一个线程。

3、BLOCKED

线程处于阻塞状态,正在等待一个monitor lock。通常情况下,是因为本线程与其他线程公用了一个锁。其他在线程正在使用这个锁进入某个synchronized同步方法块或者方法,而本线程进入这个同步代码块也需要这个锁,最终导致本线程处于阻塞状态。

4、WAITING

等待状态,调用以下方法可能会导致一个线程处于等待状态:

例如:对于wait()方法,一个线程处于等待状态,通常是在等待其他线程完成某个操作。本线程调用某个对象的wait()方法,其他线程处于完成之后,调用同一个对象的notify或者notifyAll()方法。Object.wait()方法只能够在同步代码块中调用。调用了wait()方法后,会释放锁。

5、TIMED_WAITING

线程等待指定的时间,对于以下方法的调用,可能会导致线程处于这个状态:

Thread.sleep #java.lang.Thread.State: TIMED_WAITING (sleeping)

 

Object.wait 指定超时时间 #java.lang.Thread.State: TIMED_WAITING (on object monitor)

 

Thread.join with timeout

 

LockSupport.parkNanos #java.lang.Thread.State: TIMED_WAITING (parking)

 

LockSupport.parkUntil #java.lang.Thread.State: TIMED_WAITING (parking)

6、TERMINATED

线程终止。

以上为全部内容。

显示全文