找回密码
 注册
查看: 49|回复: 4

java应用导致cpu占用过高问题分析及解决办法

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2024-11-28 10:13:31 | 显示全部楼层 |阅读模式
java应用导致cpu占用过高问题分析及解决办法
  k( J' e; Q1 r% F7 ~( F! U) @9 V8 q" k3 c' |: D

主要介绍了java应用cpu占用过高问题分析及解决方法,具有一定参考价值,需要的朋友可以参考下。 使用jstack分析java程序cpu占用率过高的问题

1,使用jps查找出java进程的pid,如 55001


2 I  H* |' U: U

[devops@ops_prod_flink_01 neo4j]$ jps

60226 Jps

55001 CommunityEntryPoint

& |) I2 [) r$ U7 R

[devops@ops_prod_flink_01 ~]$ top -p 55001 -H

2、使用 top -p 55001 -H 观察该进程中所有线程的CPU占用

top - 10:05:07 up 537 days, 16:08,  2 users,  load average: 0.10, 2.92, 9.17

Threads:  67 total,   0 running,  67 sleeping,   0 stopped,   0 zombie

%Cpu(s):  1.2 us,  0.8 sy,  0.0 ni, 98.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

KiB Mem : 24636208 total, 10156628 free,  2782836 used, 11696744 buff/cache

KiB Swap:  2097148 total,  2053116 free,    44032 used. 20841700 avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                                      

55033 devops    20   0 6395992 692476  22340 S  1.0  2.8   0:03.13 java                                                                                                         

55034 devops    20   0 6395992 692476  22340 S  0.7  2.8   0:03.90 java                                                                                                         

55035 devops    20   0 6395992 692476  22340 S  0.3  2.8   0:03.36 java                                                                                                         

55036 devops    20   0 6395992 692476  22340 S  0.3  2.8   0:02.46 java                                                                                                         

55098 devops    20   0 6395992 692476  22340 S  0.3  2.8   0:00.58 java                                                                                                         

57048 devops    20   0 6395992 692476  22340 S  0.3  2.8   0:00.14 java                                                                                                         

55001 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55006 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:03.62 java                                                                                                         

55007 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.08 java                                                                                                         

55008 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.08 java                                                                                                         

55009 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.08 java                                                                                                         

55010 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.07 java                                                                                                         

55011 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.07 java                                                                                                         

55012 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.09 java                                                                                                         

55013 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.09 java                                                                                                         

55014 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.07 java                                                                                                         

55015 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.18 java                                                                                                         

55016 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55017 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55018 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55019 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55020 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55021 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55022 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java      

" d# i7 |+ {! n7 h/ i, \

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND        

3,找出CPU消耗较多的线程id,如55033,将55033转换为16进制0xd6f4,注意是小写哦

4,使用jstack 55001|grep -A 10 0xd6f4来查询出具体的线程状态

[devops@ops_prod_flink_01 neo4j]$ jstack 55001 |grep -A 10 0xd6f4

"VM Thread" os_prio=0 tid=0x00007fae7c1fb000 nid=0xd6f4 runnable

"Gang worker#0 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c024800 nid=0xd6df runnable

"Gang worker#1 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c026800 nid=0xd6e0 runnable

"Gang worker#2 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c028000 nid=0xd6e1 runnable

"Gang worker#3 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c02a000 nid=0xd6e2 runnable


0 H- ?$ X' U/ c2 x7 u

"Gang worker#4 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c02c000 nid=0xd6e3 runnable

通过这些线程状态便可基本定位问题之所在。

方法1

1.jps 获取Java进程的PID。

2.jstack pid >> java.txt 导出CPU占用高进程的线程栈。

3.top -H -p PID 查看对应进程的哪个线程占用CPU过高。

4.echo “obase=16; PID” | bc 将线程的PID转换为16进制,大写转换为小写。

5.在第二步导出的Java.txt中查找转换成为16进制的线程PID。找到对应的线程栈。

6.分析负载高的线程栈都是什么业务操作。优化程序并处理问题。

方法2

1.使用top 定位到占用CPU高的进程PID top 通过ps aux | grep PID命令

2.获取线程信息,并找到占用CPU高的线程 ps -mp pid -o THREAD,tid,time | sort -rn

3.将需要的线程ID转换为16进制格式 printf “%x\n” tid

4.打印线程的堆栈信息 jstack pid |grep tid -A 30

1 V& u/ C5 @/ Z5 P$ ^


- j6 i( u* }& t- Y7 w( q8 i) u

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:22:29 | 显示全部楼层
1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。- F' p8 T4 P0 y* o* Y7 o3 }

: A0 u/ D- w/ o+ ~% L* ]7 _2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。! W8 e4 g3 e2 B+ q+ d

# E0 u6 Z# m. J- y% Y3 n+ K3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.
+ ~) {/ h& _4 s* D0 |/ T8 K0 G* h9 ?& E. ]7 B4 N5 W) m
4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了
' r8 n: l( F7 x; R$ O6 Z
( E6 L9 h5 {4 A1 Z" ?7 ^" ^7 M  R5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。  B6 b$ N) ], T3 ?; Z8 ^+ Z4 j

8 y5 P: N0 X- S" v7 k6.执行“jmap -dump:format=b,file=filename 进程ID”,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多,飞机票:Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙;

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:23:21 | 显示全部楼层
1. 使用top查看系统的资源占用情况
* I5 i, j7 Q- h4 Atop
2 A' W: a) G/ _4 j- o" V% }$ m连到生产服务器,执行top命令,发现双核的CPU几乎全被一个PID为5739的进程给用掉了,99.2%的用户空间(也可以叫用户态)消耗,极有可能是出现了死循环。* }. W& W) \, {+ c
Java应用造成us高的主要原因是线程一直处于可运行(Runnable)状态,通常这些线程在执行无阻塞操作、循环、正则或纯粹的计算等任务,另一个可能造成us高的原因是频繁GC。
) o5 V: i: x% ^* L7 K: _0 M2 i% G; P; k* P1 H( b7 Y$ p9 D
2. 使用ps命令查看进程对应的是哪个程序
- A* u  u0 `/ c) b1 M9 Ups/ _9 m" n4 c, s. p' v! S- C
可以看出,罪魁祸首是ccbs。这里也可以使用jps命令。! b/ m' Y  k1 b- f, K
" z6 G+ m0 h; z$ M$ r$ ^3 a
3. 使用top -p [PID] -H 观察该进程中所有线程的资源占用
! y) G. L8 L- W2 }执行 top -p 5739 -H! ]3 h3 u- T  c
top -p -H' G: e) B" j2 d2 J9 D  y( j" a9 U
! L) M7 ?4 m& B! H$ I/ V* ^! D
参数        说明- _4 w# I3 o) P4 p
-p        需要监控的进程id
& s, B; V: A( V5 P% s. o) r-H        显示每个线程的情况,否则就是进程的总状态9 U$ I: r( w9 T) F* f
发现若干线程实时CPU占用率(%CPU)较高,并且处理机使用时间(TIME+)非常长,6146线程实际占有处理机852分钟40.44秒,那么如何知道这个线程正在干嘛呢?我猜测Java这么成熟的平台,肯定有可以解决问题的工具,毕竟这样的问题很多人都会遇到。
9 A. W% R$ {/ q5 `
" S+ x1 n8 t& O* ]6 j4.使用jstack查看线程快照) X6 k3 q, n* o6 i8 L8 @) m$ [
通过在搜索引擎中查找,我得知通过jstack可以生成java虚拟机当前时刻的线程快照。+ W0 F7 z/ l# M- e* q# |
执行jstack 5739 | grep -A 100 nid=0x1802( \4 p7 e- n$ K6 S( E
jstack
& V; |& n& z" X# i, ?5 c; y% ^jstack后面的参数是PID的值,nid的含义是操作系统映射的线程id,可以通过nid的值过滤上面占用CPU较高的6146线程,线程id需要转成十六进制,并且字母要小写。! n3 N/ X( N+ G  Z0 Y
通过观察输出,可以看到线程长期处于可运行状态,直接根据堆栈信息找到对应的代码。! Y: |, U5 ]6 Y; s
. T/ I% s6 w7 S; A0 f3 w
5.解决bug0 \; e. H. E+ L" d
code
0 ]* w6 {' C, T1 c这部分代码并不是我写的,很明显这种写法非常不好,一旦serviceAddressType的值不在那三种范围内,就会产生死循环,我重写了这里的逻辑,问题解决。
  e5 H1 p. |  \1 u
4 O0 h. U/ b! v- X$ b总结
' b4 A: N) b/ U$ \7 ^! j8 @任何数据都可能出错,程序逻辑应该充分考虑出现问题的可能。
5 w6 K" C, b6 K0 F我们遇到的问题,很可能别人也遇到过,要擅于使用搜索引擎。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:24:02 | 显示全部楼层
1.内存消耗过大,导致Full GC次数过多; L( f4 `: K+ _
执行步骤1-5:! P7 E4 [) U' ^

3 k+ U# @) D- {* k多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤2
7 X+ h# e+ X. @1 f" w, y; O* j1 J通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5  q+ \6 d) R* R9 M& c
确定是Full GC,接下来找到具体原因:
7 ]$ s/ C& S4 @/ t* n- J! a: P( ]4 F. q$ i
生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。( J5 j* M  A3 B$ Z
内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。
9 R6 W! h0 p9 l" r7 X2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;
' p' a9 p1 M, ?' C执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。* ^. X% N$ o6 A5 v7 b5 b% b$ Y
4 y7 v: |2 w. X4 C

: L4 M8 q. p. @! r* @2 W# d
  @2 |# V+ q1 h% e; [- ^3.由于锁使用不当,导致死锁。, E' R1 U# V  l# E: N6 n" ?- ?
执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。2 l% E6 e9 V( p/ `/ @# {8 n, u
' V  ~# I( V8 S! q1 b: l8 ]1 ^
造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。2 A( X/ T. D' j$ b9 Y' {& j
+ o) T5 e  N9 Y% y* }) Q& B& Z
# r+ Y* x% @5 D6 o  A1 O% `  x, D
, b4 J. {8 r, F% z0 b) {1 Q" P
4.随机出现大量线程访问接口缓慢。
; y1 ~3 a1 g+ B/ H# B& a' z代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。1 }+ Q  `; o& i; Y- m4 a
7 i; A' F: S; I( M1 t/ S) Z
思路:
2 E3 N- ]; k3 d+ K2 a0 F+ W' V
3 L2 W( }# X" H. X- `+ D( X首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。
. M8 G+ I7 d( u
, X# O, Q# @% o' p% |& c% V执行步骤1-4:
, {! W) ]& I' r# C8 m% M4 @* D4 E/ ~% S2 V. O% G$ T5 S( Z2 c
复制代码
1 P8 K: y( Q$ X1 h"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]: ^- L5 v2 I- C
" r+ k# t& P' T  `+ |: ?
   java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待5 C+ c' ^9 f1 d! h8 ^& T

4 J; ?* Y+ S" [( B" J8 l! I# ~( R- n    at java.lang.Thread.sleep(Native Method)
. _. d; T: Q5 w6 z) V
$ t9 l$ t: F/ a, x7 j$ C1 _    at java.lang.Thread.sleep(Thread.java:340)8 u) w  O, B) q1 ~

2 _' B4 w  f, W: k! m4 D    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)% v- i, v3 A! U( ~

3 W% m! V) w  A! L0 y    at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点
/ j% p) I1 R3 P9 z5 X$ N复制代码( D5 A7 R" ~  |, V* d
如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。关于线程状态,不理解的飞机票:Thread类源码剖析
3 k1 B' c4 s1 g7 t% t7 ~/ L- c* \. N# x. T( A' N7 x  U- ^
5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;
2 l( h5 k' d7 |& I0 C# i) K执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。
# k5 B1 c( Y% ?- M" ^8 i
& P; I# ~5 ?. i3 f+ H) V复制代码
  d: m# V' x) B' _"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]   
) y1 b$ O+ I8 o8 _9 M' c; U" ljava.lang.Thread.State: WAITING (parking) ->无期限等待
2 G; ]' m$ Y- |  `+ o0 _2 R7 Bat sun.misc.Unsafe.park(Native Method)    & a1 n; K" n) S& j# C( R
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)   
3 E% a0 N# e9 C% Tat com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点
4 X! V& J! }( z7 C) d7 Kat com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)   
# p2 J3 q' }) [' m5 C$ n5 L4 V" \at java.lang.Thread.run(Thread.java:748)
* h' m: ^' C5 c$ S4 J复制代码8 ~6 u' q" P* g5 _5 d: E) I% j9 k7 r

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:25:16 | 显示全部楼层
问题
! n7 `8 h' u' [' C: d1、无限循环的while会导致CPU使用率飙升吗?
" N8 M; P# j5 r- k9 m7 `2、经常使用Young GC会导致CPU占用率飙升吗?' h6 H( t9 @6 e$ X: z! \2 |1 {
3、具有大量线程的应用程序的CPU使用率是否较高?
& A" W/ q& X! R/ I) }) f4、CPU使用率高的应用程序的线程数是多少?
  R7 t1 C  z! @" C' @" K5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?. o& Z" v1 E& a8 W% B. T
6、分时操作系统中的CPU是消耗 us还是 sy?
8 e/ w; ^( J% \( ]8 W" w9 Y! Q* a' w9 F, D6 m5 a
思路8 H# m8 p6 L/ ?# F2 ]4 ]. d
1.如何计算CPU使用率?0 X- i" G0 u% f6 ^4 J
CPU%= 1 - idleTime / sysTime * 100
% l# b6 m0 b7 [# S6 @$ n
2 {! m- q! K2 }  B0 L; ]1 I: W$ vidleTime:CPU空闲的时间* n0 Y- P4 Q8 I5 H

1 L$ g' i2 T8 N# ^# p& n1 U" D! tsysTime:CPU处于用户模式和内核模式的时间总和
) T. g% h! q6 r" z% w. S3 c; p" k* S, S( r* I9 O2 b) ]
2.与CPU使用率有关的是什么?
4 k) c) c/ _+ \人们常说,计算密集型程序的CPU密集程度更高。
% g4 Y1 F  A+ u% I1 V0 b# @7 O
. L5 m/ f8 o6 _4 g; K4 F那么,JAVA应用程序中的哪些操作更加CPU密集?9 R! N* \1 ?$ }% x

: C# V! ]# S/ o! e, d, X0 C9 y以下列出了常见的CPU密集型操作:
: X' i8 C1 n; G7 e( W! I' r9 Y+ H2 |9 [: \& v1 R$ [
1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。
( b- F5 S# c* |0 ~/ z2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。
  Y1 n6 @8 G* V' `$ v* g, j* b# i3、序列化和反序列化;$ s( ?% ^" N+ H5 h; ]) g
4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。/ g4 W; F3 _2 ~. e- U% L' O8 n
5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。# n, h6 j8 Y  F* l
6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。
2 _8 T' y" z; x2 G: t7 N  l  B3 T# ?: l4 _  l$ D) J6 `' p. }5 m
3、CPU是否与进程和线程相关?7 v+ l2 X0 j& ?* @" I5 Z- o  R8 o
现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。) y& E! S6 t8 b  W# G0 H4 B

/ N/ p6 m; b9 T4 \! x* N; o% n答案- [0 `* b  u, x: }7 g
1、while的无限循环会导致CPU使用率飙升吗?
# G, Z4 ~6 g0 c4 I是。
" x/ W7 Y4 K2 c+ X* G6 v9 ^, o" ^2 K4 A) T. P/ O7 F" C- r; ]
首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?
3 M  U9 X0 m+ D* `9 d" I: K8 y, E0 e6 p+ m) ~( f. l/ `
除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。整编:微信公众号,搜云库技术团队,ID:souyunku
' u8 F1 P$ U# x" X
! j0 r$ v. d! i! s+ N$ x( l3 ystackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?* w* i6 ^$ F5 a# C/ w: X. |

$ L: n* p  k, Z) F8 W1 Mhttps://stackoverflow.com/questi ... ncrease-the-cpu-use  K( h% }6 U, v9 ]- L" v
$ T( h' b$ ^6 w- q3 m1 e1 U/ K
2、频繁的Young GC会导致CPU占用率飙升吗?9 U& d- ]3 |) }, b
是。
) t5 z" v' n9 [8 g* J) l4 T5 f) i$ A9 i! k
Young GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。" _7 C# j* T$ z

) \# v4 c0 `( T9 `让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。
& G$ E( P4 _2 a8 _; i3 C9 S3 u8 Z8 I. |% M8 G! A
3、具有大量线程的应用程序的CPU使用率是否较高?
3 r4 o+ h7 O) ~: t不时。9 q7 O+ ~- [# G* c. n1 l. `& J
6 ~, j4 Y! _* Y( G% |( V
如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。
( Y; ~! S' |7 ^# C4 w
2 J  D( p( v- d" M, V% R我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。
1 Z! M0 X# F! {9 Q* a
' n) P8 X7 A' u; q9 U但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。: ]: O, Q; E2 `. u6 [' w

' p$ S% h, S) V4 ]4、对于CPU占用率高的应用程序,线程数是否较大?
6 R+ k, j* V! o不是。$ C1 z$ s! ]* r: i

' j9 D* E8 f# I+ U( A4 b高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。
2 R4 {/ K; y: R( y! ~6 ?; Y, @+ v7 x, H' k! g# s
5、处于BLOCKED状态的线程是否会导致CPU占用率飙升?" _+ `! A% Z- s8 I* Z- N3 ?
不会。
  \! ^! V8 I6 a) C- ]
# K  m: }" i( o& k7 `; R3 u& A* HCPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。
$ b7 b. v3 U- i: b$ F3 A) G9 C# P- h
6、如果分时操作系统中CPU的值 us或 sy值很高,这意味着什么?
! s: m$ P$ f. M- c# F9 D0 x您可以使用命令查找CPU的值 us和 sy值 top,如以下示例所示:
; U" P  N# e7 t" k
, {* C! g$ E* r  d# C3 I" a' Z7 S- a, h/ r) _9 j
us:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。整编:微信公众号,搜云库技术团队,ID:souyunku6 b4 {6 n4 h" l8 I2 d! Q( n

% U" j7 l8 w4 W4 K: S- a( g0 p) m% z0 Y4 tsy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。
- \* P; w6 g- W7 \
: q+ s+ |  e0 \8 g经验* b( y5 O% c( o9 s& G: |
如何找出CPU使用率高的原因?下面简要描述分析过程。( E0 z" f1 l! J! O

/ L8 {  J& p0 J6 m0 m- R如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。
  \* j8 e1 l7 u7 v3 j- X0 Q5 m5 ?( y: r9 F/ @% E0 n# r* M
以下是一个真实案例:1 l+ l3 k( H) l

* T' q! O8 P' d2 `9 n& t7 `2 K一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。
% y6 d. O& X) o$ p% s7 k$ C) }1 O" P8 r3 l9 d: J( F$ N

5 G3 l9 I1 o1 O进一步检查日志:- m/ X$ G: {& k5 `" Q

. Q1 `" ^/ k: N( n4 Z. H代码语言:javascript6 D: [) ?! T5 [, k6 O  ?. @
复制
. ^; r$ k) e# \$ p0 Eonsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE* L- x8 ?4 M# D1 g: w
stackTrace:/ f9 X8 C9 T3 `$ o5 y, e
java.lang.Thread.State:RUNNABLE- W/ [/ d/ C5 o* A; Q7 N
at java.lang.Object.hashCode(NativeMethod)4 z8 r. n! ~) g
at java.util.HashMap.hash(HashMap.java:362)
* H' d/ {; X9 T- Q; \( Y; Pat java.util.HashMap.getEntry(HashMap.java:462)
, G) v3 g5 s; N2 [at java.util.HashMap.containsKey(HashMap.java:449)
) @) W0 R3 {: l; I7 g2 kat com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)
" w. c2 ^6 q3 S1 p0 E1 gat com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)5 v# Y& }0 h7 C) ]4 s+ R
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)! i' L" q5 W- j% I/ O3 z3 j
at com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)7 z% U* T9 I' G3 e
at com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)* ]! D$ R) X, a* {' M9 H- H
现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-11 23:13 , Processed in 0.018967 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表