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

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2024-11-28 10:13:31 | 显示全部楼层 |阅读模式
java应用导致cpu占用过高问题分析及解决办法5 \$ q/ r  m6 Y( _* ^9 C

% Z5 B4 l1 S$ L( q7 U; F$ J4 r

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

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


0 j# O, m* s2 D* t

[devops@ops_prod_flink_01 neo4j]$ jps

60226 Jps

55001 CommunityEntryPoint

: K! h+ e) \7 @/ G6 t" e' }$ 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      


1 f) j: `% f8 {% N" u

   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


% `: V- B) }( l* ?" q

"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


* \/ t: \3 O9 B: S* Y2 W* E

+ a7 R  F3 \3 P  Z2 {6 R. ^

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:22:29 | 显示全部楼层
1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。8 I- R0 Z+ D# P) ]

& y: z, H4 l. p9 A4 O& W2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。' [( a: t: r) o: d
5 `% q4 }3 O8 @$ L- v6 q& f
3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.( m; c: I3 f1 O  n6 g
7 c" M1 E0 X0 p* ?% J, e8 b% m/ w
4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了
- O$ I* ]. P& g
& J$ e6 l3 J) G' G  X5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
/ o" g& E1 v+ ^4 p3 \, k5 ~0 M# N' x9 m7 n
6.执行“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查看系统的资源占用情况
& @2 ?9 E/ ]# \! \) Htop
+ g: F) x- Y  Z$ r# H' @连到生产服务器,执行top命令,发现双核的CPU几乎全被一个PID为5739的进程给用掉了,99.2%的用户空间(也可以叫用户态)消耗,极有可能是出现了死循环。4 u* g. G! {* S+ v! l5 s
Java应用造成us高的主要原因是线程一直处于可运行(Runnable)状态,通常这些线程在执行无阻塞操作、循环、正则或纯粹的计算等任务,另一个可能造成us高的原因是频繁GC。% |6 B7 a9 A9 q% R& b

6 p: K6 ^8 c3 E8 n' w) E# n% }2. 使用ps命令查看进程对应的是哪个程序% J4 y* t7 @9 T# U7 N0 g9 V" L$ D
ps
4 t9 _. I, c/ ?/ Y- ]7 W可以看出,罪魁祸首是ccbs。这里也可以使用jps命令。
3 g7 t0 L0 Y! {5 d/ w1 d/ [0 n; F' [3 b5 o2 ^1 A8 f. Y; v" s8 C; w' l
3. 使用top -p [PID] -H 观察该进程中所有线程的资源占用- }& N! C9 b) O( r- i3 E
执行 top -p 5739 -H( V9 i/ K, r; A0 E
top -p -H9 Y) y4 |/ S% k$ m& F" H- H9 @7 \' U

5 E* i" M1 F9 k6 n+ A参数        说明8 Q5 v: w8 n' c: \) f, s9 y
-p        需要监控的进程id6 g3 P; z/ Q$ v* L
-H        显示每个线程的情况,否则就是进程的总状态
: k  D$ l* o. U5 u. \) {) i" [2 x发现若干线程实时CPU占用率(%CPU)较高,并且处理机使用时间(TIME+)非常长,6146线程实际占有处理机852分钟40.44秒,那么如何知道这个线程正在干嘛呢?我猜测Java这么成熟的平台,肯定有可以解决问题的工具,毕竟这样的问题很多人都会遇到。
7 e0 M3 ^6 d$ t" W( |5 u" }, w
/ ^8 @9 D1 R8 y7 m* v4.使用jstack查看线程快照
, @8 c5 F6 r# O通过在搜索引擎中查找,我得知通过jstack可以生成java虚拟机当前时刻的线程快照。# x- ^+ C1 R. C5 g. w0 ?
执行jstack 5739 | grep -A 100 nid=0x1802
  q. R" _: U. [0 n, Vjstack
7 m4 ~3 Q, L7 x: H$ r3 x& z! w/ xjstack后面的参数是PID的值,nid的含义是操作系统映射的线程id,可以通过nid的值过滤上面占用CPU较高的6146线程,线程id需要转成十六进制,并且字母要小写。* B/ d& j! E' G" Z9 I" h# T: Z
通过观察输出,可以看到线程长期处于可运行状态,直接根据堆栈信息找到对应的代码。7 k5 l  v: j. E5 p
- Z( k- o& `; X  m3 m2 H
5.解决bug3 l6 T+ j5 z$ J/ s9 ~7 n. d
code% b  k/ q# L- E% y- q
这部分代码并不是我写的,很明显这种写法非常不好,一旦serviceAddressType的值不在那三种范围内,就会产生死循环,我重写了这里的逻辑,问题解决。# V& B4 W: Q- r

/ ]/ Q6 r6 i9 [2 u  T( d总结  l- x( o8 I! N3 u: y" b" j
任何数据都可能出错,程序逻辑应该充分考虑出现问题的可能。
1 l- @0 E  n) k我们遇到的问题,很可能别人也遇到过,要擅于使用搜索引擎。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:24:02 | 显示全部楼层
1.内存消耗过大,导致Full GC次数过多" E6 W" x& b1 S* r4 f; b
执行步骤1-5:) \% v/ K2 ?# t0 F& v/ }/ ^) B

# N: f, C$ Y% j- z: P( f. N多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤2
* A+ `* ?$ n6 w& J通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5
# u- a9 a% z: y+ b% G6 K; E8 @) L确定是Full GC,接下来找到具体原因:/ c. y9 S  F& B8 M4 d( m

: H4 ]3 f+ L0 G$ s生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。
+ c; z- c* k& I3 z: w1 f内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。5 K5 X( W9 e% B
2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;
8 g9 A3 f2 a! N  [' r% }- F( h8 R执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。
: P4 ]1 N( p5 V/ O( t
2 V) r* J: g' j2 ~
6 t) T8 B* X. _5 ~( B
6 p* ]3 U% e+ o+ b3 C3.由于锁使用不当,导致死锁。9 Z' h2 k  D2 o7 q% G1 a- Q& }
执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。% I5 u6 k, t7 g& o$ T& O$ N

- T0 l) m1 [/ O! B2 Q造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。
* @  N# d/ U% N$ k& G) m$ `! `* w8 [% Q5 n- P( r5 W
* V3 s! f+ x8 q" k% y7 {. R# R8 _

* z3 g( J# ^8 Y' F6 _1 C! ?8 [4.随机出现大量线程访问接口缓慢。
. p% K0 i5 D8 A; x! `代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。
3 ?- B9 N% G2 ^' E" v9 B! m
6 f* u: U5 o3 I0 H* R1 c" N* Z思路:9 `. ^$ U/ C$ R+ O$ d/ ]- X
! S4 C7 Y0 A/ v$ d& C4 ~# O' s
首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。" h, Y  ?6 @: w3 w7 \% Z$ `9 [

* R/ }& E; y* B! b/ q8 H% a# K% b执行步骤1-4:
# }  T& g& j$ s  b& z2 G3 [4 x: F# }( I0 ?; @3 P
复制代码
, W; ?5 e/ l, |  X0 [3 ~5 M0 i"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]: Q5 Z' @- }9 A9 g0 E
; Q* E6 R8 o( V5 Z2 u: T( Q
   java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待. D5 E. I" L4 D  [. X- H: M, g' Q- d

4 R/ i5 E; z4 H: p: ~    at java.lang.Thread.sleep(Native Method)" d1 H( b- l. {/ [0 r, a
: d6 K6 G5 _$ u% |1 G; M
    at java.lang.Thread.sleep(Thread.java:340)
! A$ J  z% O: j  `, T, W
5 A% D" P- p/ ~7 m  V9 _+ z    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
! {( C+ d2 {% B8 |+ _
$ j8 n- `- |8 r3 W7 o: q8 x    at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点
4 y: _' s6 e- p9 f7 t* @1 q! y复制代码4 ^6 H3 f" z, R6 y. b
如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。关于线程状态,不理解的飞机票:Thread类源码剖析
$ z: X/ a: ^( b8 z4 z. P/ c
" U9 v% p: e2 t  n0 A2 A5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;- v+ T/ @$ M8 B& U
执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。
4 X* r. G. ?# f! \/ C$ R$ G) O/ S$ Z  Y8 s4 X2 H7 ]0 N9 E+ \
复制代码
% t- N$ c1 w9 R  C"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]   8 }6 X  y$ @! G; W
java.lang.Thread.State: WAITING (parking) ->无期限等待# w1 v6 W0 m/ S
at sun.misc.Unsafe.park(Native Method)   
- n! @$ }. O9 ?at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)   
. ^* v! V) O& @4 v3 X0 M2 e9 n) B8 mat com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点
( V. b, v, A# l/ _at com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)    - H5 d* d+ v. _4 S
at java.lang.Thread.run(Thread.java:748)1 U% e8 s6 A% S6 j7 Q/ I
复制代码
; |; U5 X7 T8 u5 M( Z* e

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:25:16 | 显示全部楼层
问题
# t$ h) H" f# R; S4 D) V4 ^1、无限循环的while会导致CPU使用率飙升吗?
! ?) e% e8 D9 K6 K3 Y! `, x3 ^2、经常使用Young GC会导致CPU占用率飙升吗?8 }3 h. |8 |2 B* Q8 J
3、具有大量线程的应用程序的CPU使用率是否较高?3 g; V" Y8 }( Q' v- N$ z
4、CPU使用率高的应用程序的线程数是多少?
5 l3 u1 x1 X. |5 u; ~1 s  g5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?* [4 m' U; I) ~* Z* z% B5 E
6、分时操作系统中的CPU是消耗 us还是 sy?
- t( e. O. t, P% }0 V" D9 T8 r# j1 I! O5 d4 Z& O& A
思路
9 J* e; k0 w- W$ ~6 O1 m7 G7 {1.如何计算CPU使用率?
0 z: r. O4 w+ `5 m3 JCPU%= 1 - idleTime / sysTime * 1007 i2 ?, y9 b3 I  [* z

/ m. M+ v2 y9 e% d- GidleTime:CPU空闲的时间
' [2 e% S8 d' Y# `: A9 r9 j$ c
9 v+ f' b1 \3 K( p) w& ^sysTime:CPU处于用户模式和内核模式的时间总和( T7 }" p; }% l  C

) [6 T1 N4 R+ V7 P9 I1 D2.与CPU使用率有关的是什么?0 ^2 p0 b- t8 I9 L" g1 `: B
人们常说,计算密集型程序的CPU密集程度更高。3 u( f9 _+ y* W: I% m

+ o* y& J" R  q那么,JAVA应用程序中的哪些操作更加CPU密集?
: ]5 A. o) i; Q
+ [7 X* g) \  }$ V+ l9 D' ^以下列出了常见的CPU密集型操作:7 t- }% L5 o9 {/ c1 j7 E
6 _9 b2 P- ^9 _/ I' f, k4 M4 }0 H/ g7 l
1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。$ L: d! Y1 D2 o' o
2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。8 R5 l' g1 q* q; v% L3 j$ f
3、序列化和反序列化;
; [5 H" }# j" s' Y- M/ a1 _$ [4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。3 U1 I) U$ c" _+ W0 @1 e
5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。
$ m0 Z9 R( G& [6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。. ~0 m* g# U( I* f! v* J/ Z, ]! b) `

3 q1 [; L  g! y1 h1 Q5 h6 _) j" N3、CPU是否与进程和线程相关?' }4 z7 W! U9 B# H; S
现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。5 R7 x* y$ N8 M. k$ B/ c9 G3 n

! |6 R+ S  F1 d& u3 @答案5 [' g- [% G* z4 }
1、while的无限循环会导致CPU使用率飙升吗?
/ _* j$ p8 ]- S3 i& }是。2 ~6 I6 @. S$ s% Z+ j* M) m

( h( O0 B# H4 E1 Q: f首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?% Q* t5 C: g- M9 v6 [5 G- t

, P/ n) a; ~9 f7 t除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。整编:微信公众号,搜云库技术团队,ID:souyunku
/ I1 {: b: w2 p! L1 }3 F3 ~4 C& L" [) D4 H
stackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?7 ?; E! C4 h( U" D/ _1 E

/ g4 V8 S, b) C0 bhttps://stackoverflow.com/questi ... ncrease-the-cpu-use
& r, d2 ~" I/ B3 J0 O' N* N5 c: r5 B0 J# x2 u/ k/ M
2、频繁的Young GC会导致CPU占用率飙升吗?
3 P1 v( `" o; p# ?9 C是。$ S% Y' w. S4 _$ u" r7 U4 |/ ^& @
7 R6 m* c. ?+ j) }
Young GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。
+ l- w; y$ D- d7 N0 x# K
" z2 W) Z$ y7 V" u1 v2 e让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。% A: S5 [( p1 R: W
, e) S0 @4 z; y
3、具有大量线程的应用程序的CPU使用率是否较高?
. J/ f" s8 H: p# r/ G# `+ O' Z$ @3 K不时。9 h6 G, y3 ^6 b* P; g) q

3 Z1 x  M" X/ K如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。) \* |1 e2 x% v8 V/ l3 ]) W9 V
4 R6 G# H+ u) L6 U: N7 E. }
我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。
# H2 B  P1 O7 D, d1 I  [- J4 F4 b$ C9 a; A. y
但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。& m% }% H$ b/ @# b2 [! [+ x+ ?+ O& b

# v1 L& }# P2 P4、对于CPU占用率高的应用程序,线程数是否较大?
6 u7 {. n7 O: B: O" X9 h! z+ s: b9 j不是。9 w& a  F1 f) h

+ \& O- R+ }3 Y* b- V% V5 c2 t高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。- P3 k- _- I$ g# f2 h8 T) Q
2 m7 a6 x1 s' V+ i" r
5、处于BLOCKED状态的线程是否会导致CPU占用率飙升?
, G0 O7 x4 L4 s+ C7 q8 y不会。# j% R5 u( y9 p

' a4 N! Q3 f1 k1 P* bCPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。- Y# P, z0 `& c; M
2 U6 N5 c/ H2 ~" f+ ?
6、如果分时操作系统中CPU的值 us或 sy值很高,这意味着什么?% p  e5 s# u( X
您可以使用命令查找CPU的值 us和 sy值 top,如以下示例所示:
" C: t" |8 x# j  Y% p# T: F" [- r, N3 M* m  f- _  E

3 a0 z8 n6 n" \: N8 j1 Ius:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。整编:微信公众号,搜云库技术团队,ID:souyunku
  G! ]5 q! Z3 l, W9 ^) P" X& `( k# H3 [7 H
sy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。
( v; \: g8 B2 N8 b- q/ k& i7 N
# `3 w/ b- w( L) x/ v9 ~经验
- ]8 [" k; U; d2 o如何找出CPU使用率高的原因?下面简要描述分析过程。
$ b$ U. z! c$ R" U& \- m; S
* o& c/ m/ h6 d如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。7 ~# \( [6 O) }
9 d% H/ ^' z/ \/ c% n4 l
以下是一个真实案例:2 U& T2 w: S8 w1 K$ ?" w
1 `8 `+ ~) T8 Y0 u% x# C( M
一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。9 n; R, W0 O' d) F

$ F  a0 p1 S, U% V: m' i9 Q
6 w9 Y: i: w/ F- J8 [进一步检查日志:
8 R1 h3 V' Y( u9 C% s, i9 s' P, H$ |+ ^( Y9 v6 N
代码语言:javascript
0 D% o3 J, ]) }$ G& ?/ g! C复制7 V! r0 {; h# S$ y. j  K
onsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE
/ h/ F: Y, ~' a3 N5 y! z; ]- bstackTrace:
% i8 e% c5 f) u% R% }( d9 Xjava.lang.Thread.State:RUNNABLE$ s+ \9 M- P; Z3 z/ U9 M$ d
at java.lang.Object.hashCode(NativeMethod)9 N7 m  P8 m% b3 {0 j2 z$ I% }: O
at java.util.HashMap.hash(HashMap.java:362)
+ s) _1 \! X- E8 Cat java.util.HashMap.getEntry(HashMap.java:462)
- M3 c2 L$ N) ]at java.util.HashMap.containsKey(HashMap.java:449)
/ k3 u+ r2 E& M$ @/ k; T0 o' c. S0 bat com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)" B* C0 v1 ~0 |& t3 J8 C! K
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)! _: Z  ~2 r$ E! u6 Q: e0 y
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)
' ^$ g) R8 `2 p! qat com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)0 v0 l5 [' k& B* M
at com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)
8 \6 D5 s2 x: H现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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