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

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2024-11-28 10:13:31 | 显示全部楼层 |阅读模式
java应用导致cpu占用过高问题分析及解决办法
4 g' K3 S9 [; h
7 ~( n1 ~5 }1 x# c2 r5 z

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

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

) S0 q9 K4 z: u+ O# r6 ^  f8 c4 R

[devops@ops_prod_flink_01 neo4j]$ jps

60226 Jps

55001 CommunityEntryPoint

9 w& u* q, R( g) T6 \+ L/ {$ ~

[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      

9 G* y$ c4 Z; X8 N7 T7 g

   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

3 ]7 V) ~9 {$ {+ b# d0 F3 ]0 ^

"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


8 z7 C0 D. G# A4 w- n! V


1 k' m" f7 S+ b: q' J/ b

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:22:29 | 显示全部楼层
1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。
% f6 X" K5 [$ y! s3 r5 ]! t3 f5 L; U
1 F0 d0 x( H/ C4 v  |% v0 y2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。# g- D7 A8 b* V+ j4 L

: N, c" }+ e! L3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.$ Z* G$ W. H' z. x* x4 Z
0 S8 s% P% m+ F  A6 I1 m8 i
4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了
3 D) Z8 |1 I' b. v+ Q2 n; m% e# A) t) C- E" J8 `
5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
# H! b) f4 p& e: b2 S- c0 \6 i' t7 M# Z& S* \, I
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查看系统的资源占用情况
) G" ~0 p9 G& c# t* @! M- wtop
0 s6 l( @% ~6 X! X7 B. S0 i2 @连到生产服务器,执行top命令,发现双核的CPU几乎全被一个PID为5739的进程给用掉了,99.2%的用户空间(也可以叫用户态)消耗,极有可能是出现了死循环。1 c/ P. r7 d7 m8 @- q2 {
Java应用造成us高的主要原因是线程一直处于可运行(Runnable)状态,通常这些线程在执行无阻塞操作、循环、正则或纯粹的计算等任务,另一个可能造成us高的原因是频繁GC。
) w' d1 a" E1 V' ~  H# J7 E
& B% Q; t1 I3 g; q, p2. 使用ps命令查看进程对应的是哪个程序; H, [4 O+ O* \: R7 L
ps0 b9 T; f) G9 K0 m
可以看出,罪魁祸首是ccbs。这里也可以使用jps命令。* z8 {8 Y* v" U# l6 s( ?

" N7 Y+ T5 i3 s+ Z# I8 }3. 使用top -p [PID] -H 观察该进程中所有线程的资源占用
1 `( Q- w7 k! O% U+ v+ \执行 top -p 5739 -H$ F5 c3 B; Z7 F5 M
top -p -H: Y# \, h  ]( d* t$ k8 E* Z; J( i
; `/ J4 Z. d' ^. E  c
参数        说明
, e2 R( t5 M- O% }2 ?) \9 o-p        需要监控的进程id5 ~' i7 E7 _. B# G% z' G
-H        显示每个线程的情况,否则就是进程的总状态6 M0 L5 T* ?. o5 @  E) q  d
发现若干线程实时CPU占用率(%CPU)较高,并且处理机使用时间(TIME+)非常长,6146线程实际占有处理机852分钟40.44秒,那么如何知道这个线程正在干嘛呢?我猜测Java这么成熟的平台,肯定有可以解决问题的工具,毕竟这样的问题很多人都会遇到。
, ?& |1 _0 R% j
* X& l' h9 s  r5 s: ^4.使用jstack查看线程快照6 K0 H/ x& z/ Q' }3 x, B$ O
通过在搜索引擎中查找,我得知通过jstack可以生成java虚拟机当前时刻的线程快照。! Q5 \2 j& J9 p, o3 T
执行jstack 5739 | grep -A 100 nid=0x1802
, ]7 d, f4 k0 xjstack' M8 W7 G3 o$ c# k
jstack后面的参数是PID的值,nid的含义是操作系统映射的线程id,可以通过nid的值过滤上面占用CPU较高的6146线程,线程id需要转成十六进制,并且字母要小写。0 l* n3 R) B  j
通过观察输出,可以看到线程长期处于可运行状态,直接根据堆栈信息找到对应的代码。
, J& |& S' q2 h
6 c% g- g9 x5 W* B5 X5.解决bug
4 k  {, C: `# C7 Z6 D  [code6 P0 q! Y) ?  v/ f/ f  Q6 r
这部分代码并不是我写的,很明显这种写法非常不好,一旦serviceAddressType的值不在那三种范围内,就会产生死循环,我重写了这里的逻辑,问题解决。
3 I3 f$ U; h& [0 k: D9 x9 _4 x# @# p1 s, B' [" \
总结0 H* {+ g% ~+ f6 x" @3 @7 Y  e
任何数据都可能出错,程序逻辑应该充分考虑出现问题的可能。
: i1 K7 s7 ^3 [0 N. s我们遇到的问题,很可能别人也遇到过,要擅于使用搜索引擎。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:24:02 | 显示全部楼层
1.内存消耗过大,导致Full GC次数过多
8 s8 @" o: f. L% L执行步骤1-5:; u& F: t" F7 j$ R& X2 z9 k3 D
% J1 Y- ^" R1 K) x, l7 f6 o# F
多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤2
- n* O' b/ `2 I% g- _: J: [通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5  A1 ~! N6 a6 K0 f% B' J4 _' ~( N
确定是Full GC,接下来找到具体原因:; W. p/ p) p1 ]5 I# k9 i' ]

/ @+ \& A; J6 A8 Z. z生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。
' l! R; i% |' J. \) l' \* h内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。
& m& {2 U, t0 }' D/ V' E& P8 p9 }2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;: F' V/ A2 a1 s3 O5 T6 x
执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。
( q: K9 K3 D6 _/ @8 H5 b1 F! A! F$ L) H
0 H2 R6 H& p+ ]1 J( J/ Y' S1 E1 x

- S& [% v6 J7 n) s  r4 k6 s3.由于锁使用不当,导致死锁。# ?* C: Q6 W7 u7 n. r
执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。3 a4 c) ]  G# B+ A! l

, }, n+ t) ?5 f% @4 O! |( C造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。
; @0 c  }4 X3 o' T, ^7 r! ?$ g  ?' z; Q2 W5 F
) Z7 B/ o, G7 F; A/ Y3 `9 e
3 Q9 I) [& j7 p! \( ]& u6 |
4.随机出现大量线程访问接口缓慢。
; c# m4 C4 I, t. N代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。
) a' z$ _+ V* E1 l0 H( C9 E: G: o8 Y( @
思路:
+ L- j$ m3 r! l/ _' ~5 U& m, l
4 s0 N9 {7 R) d4 E! X. D首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。- Y" r' ~  r/ ]/ l
+ e4 W. _2 T$ c. H; t- ^
执行步骤1-4:
, F; G6 ?* W: h4 p+ x8 Y% m8 h$ p. o9 t, e
复制代码
9 v( u7 U" x1 @& F% T"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]
. `! h3 C7 ]$ _* n4 {! [3 M: k" m
   java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待
) T8 M- C2 n2 `4 i. v/ X+ w# G
' S6 Z& D" g$ M! s$ H* {) `    at java.lang.Thread.sleep(Native Method)) `6 {% o$ E1 \7 p0 N1 n

0 ^6 ~) q# w" n% o    at java.lang.Thread.sleep(Thread.java:340)
. |9 f$ t% j4 r8 h& w: C0 L( y" ]# u4 y" j) E# h7 M
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)7 o# ?; P7 d& V( c& k( M$ N
/ F9 O7 V. b7 L8 H; V9 o
    at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点
, D* o3 s& |- d- ^+ o复制代码
+ @* K( z+ k$ X% s; t如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。关于线程状态,不理解的飞机票:Thread类源码剖析
) v: _5 U0 f& U3 m# M2 t0 c( M# G" Z, Y7 T- T* D( C- o/ U; @
5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;
" d  I0 A( Q" o6 a* q0 A! R/ K执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。3 v6 x' T1 ?7 @2 J8 X  P

0 z/ l: Z% O0 |$ z  I1 ^" _: P' @8 s) v复制代码* o, h' l% M1 y; ^5 I
"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]   % B4 O( P4 e; B
java.lang.Thread.State: WAITING (parking) ->无期限等待1 ]! v! B% Z- D
at sun.misc.Unsafe.park(Native Method)    1 T" }' W3 i) n" r$ i
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)    . I8 X8 d% |' o$ s, _
at com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点" j: l( e! k0 L9 }
at com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)   
$ M( m% q& Y$ I+ Y+ Hat java.lang.Thread.run(Thread.java:748)0 n2 k0 y; t0 Q" a- J) u
复制代码
" D1 e: m* ]; @* e$ \" |& o+ [

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:25:16 | 显示全部楼层
问题
0 Z$ t' m" n. p& F! s1、无限循环的while会导致CPU使用率飙升吗?
( j" v; x  N6 F, B5 I6 P2、经常使用Young GC会导致CPU占用率飙升吗?
/ E1 W: }3 y' A2 m% F- Y3、具有大量线程的应用程序的CPU使用率是否较高?
7 v; c- P" e9 y0 p* G$ [4、CPU使用率高的应用程序的线程数是多少?
; \# W( T) _* V% R  \5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?" E; s# T1 u1 I: ]) S2 j
6、分时操作系统中的CPU是消耗 us还是 sy?% B$ m0 _3 Y# ]* n7 @) O6 f9 w

; ]# E; L. @2 U) n/ ~& `. F5 j' N思路7 X& v. r2 W, @; ^% a0 l3 E2 l
1.如何计算CPU使用率?
/ g. y% Z$ T) L: ~: uCPU%= 1 - idleTime / sysTime * 100$ @9 K. A- s1 M& O; O: x' m
0 h$ ^9 P* u1 L, F# F# z
idleTime:CPU空闲的时间; a: k) n6 `0 P9 D; L1 K. \# a- e

; K# i  b& r2 gsysTime:CPU处于用户模式和内核模式的时间总和
  ]$ M6 D! a& s  i2 p
" M* q* b+ F- l8 q# z; [2.与CPU使用率有关的是什么?/ Q) x7 B; q% D+ ?& X1 P6 N
人们常说,计算密集型程序的CPU密集程度更高。3 H0 e# T; ]8 k7 j) R
1 `0 @6 N$ ?6 ^0 k. m7 G) ?
那么,JAVA应用程序中的哪些操作更加CPU密集?( ^" Q& S1 H+ Z0 u

8 b8 d1 t1 m' r. m# ~+ d* }以下列出了常见的CPU密集型操作:* E! B( {: N- S. x; V' m$ B3 Y! Y# O
+ ^0 S# f, W5 M# u: S$ W8 W2 a, Z
1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。
! C7 \9 G7 @6 `2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。
, O$ s) f# i2 r3、序列化和反序列化;* e5 {2 i  o$ W/ {' ?: e
4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。
' ^$ d+ K7 J/ ^& T2 |" l5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。
# p5 E* j0 Y) o- A; i$ y" J# H6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。9 t' \- S9 X) }; a& s) H( ^

& S* _- a; A3 V5 L6 W3、CPU是否与进程和线程相关?
1 A4 x6 I. c" ~9 n* W现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。
+ k/ j! _0 u% A- L6 A- c
& H3 G9 R, @2 n; D答案. S  f/ R1 B( Z) d" o
1、while的无限循环会导致CPU使用率飙升吗?
  M4 q; R1 ?) [是。
/ Y" D( k1 C% o2 f7 A; i: v
9 I* O* [) ?5 h* S5 b" I/ t% j7 r0 P首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?
2 `: j# v# c$ |& f. `6 J0 p$ Y" K, `/ e3 n3 N4 x; X0 }
除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。整编:微信公众号,搜云库技术团队,ID:souyunku
1 k" [% n* @& [0 \  X8 t4 I6 i0 `" g8 h2 `( a7 ]
stackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?1 P' W7 j  i) h' G9 G; I7 y" H
( u, h3 j1 Z7 @& ?+ {6 ^9 F
https://stackoverflow.com/questi ... ncrease-the-cpu-use
3 W  J' z. \3 ]5 A7 |- r3 l2 ^
2、频繁的Young GC会导致CPU占用率飙升吗?' m9 N# S9 C9 _- ]" h, d
是。$ M4 g4 p. s  Z- X/ n! ?; |- K; Y: E

6 L2 n8 P0 I$ x8 WYoung GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。6 r7 J. a; ]9 N+ ~4 P
% g/ G; n! E' l" g; g
让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。* n  V& n1 S5 A# }4 j7 ~% J
8 l' f  b& a) u& c9 p2 Y5 n. [. m2 a2 I
3、具有大量线程的应用程序的CPU使用率是否较高?
; I$ l% z6 n6 M7 K7 u不时。
) C4 L/ j) c5 q9 c
( b) {  v8 N( P1 s如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。) w% R1 p+ r& n# a
/ B1 ?/ J3 I' I: h; Y2 g
我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。+ i+ v' V' D# E7 d

3 q. L! ?0 M- ?3 F! }但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。6 b& K4 _  D2 H
  \( W) i, h! K0 ?7 l0 E; k' x& i/ u
4、对于CPU占用率高的应用程序,线程数是否较大?& W. [$ r$ d$ t: c, Q  P
不是。8 B( r1 P4 w5 M7 Q
5 C4 ^; f8 F6 }# W* |
高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。
% ~# S8 @' W) k5 x# y; D
- y$ W) R- L" Z+ P! K5、处于BLOCKED状态的线程是否会导致CPU占用率飙升?
6 m! ~- F5 u* ]; D! ^# D: m不会。
; ^- W: B6 T- V* \
; v7 n6 i$ B2 T& P7 bCPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。8 K+ U; V& F3 `- w8 e$ A/ c

+ J) k# H' ~7 K" [; K6、如果分时操作系统中CPU的值 us或 sy值很高,这意味着什么?+ f& P$ L$ x( M9 Q' X9 f; }
您可以使用命令查找CPU的值 us和 sy值 top,如以下示例所示:5 N0 ^/ t; k1 y

' z6 z; a% ]  G. e) `2 R& s# F6 ~2 R2 V8 o, A  r$ A
us:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。整编:微信公众号,搜云库技术团队,ID:souyunku6 \& x! P5 S" ~% O; b
: }+ h# Y. _# s8 S+ |" C; W
sy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。' M  y% u! O% i5 E

; w8 L$ C% J6 Q' [* P, a. q经验7 d; X9 y  E8 h. v) d  h
如何找出CPU使用率高的原因?下面简要描述分析过程。+ _+ Q2 A5 [' Z

  E/ g, t8 R$ W; s/ i% O! p如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。
$ c! D: _' |# g3 s- r  @+ i0 G! G( C" I% P9 o. _2 h# P
以下是一个真实案例:
6 C: q! _7 @9 k' x
5 P$ `+ r/ q: I9 Z/ f  U一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。& A+ A3 C* f" J- w. E& c2 t

3 g$ T1 a5 c  D3 |2 W
/ t6 ^# Q2 [1 }' A: S" Y. G8 y1 Q6 s进一步检查日志:  G% `) O' e3 p5 t: j) b+ y0 _8 B' H! ]4 [

8 J( J6 p2 _$ G  Y& q7 c/ Q$ P) Y' P( l代码语言:javascript( N, \2 z* R1 ~1 t6 G6 q* w1 D* B
复制
5 I% K3 ]+ ^" ~) Uonsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE" @% b, q! Y7 ?# S
stackTrace:# M) S  {4 L) j+ L% e4 x
java.lang.Thread.State:RUNNABLE! ^; \. i' e" ~
at java.lang.Object.hashCode(NativeMethod)" x( K/ I/ _8 _; s
at java.util.HashMap.hash(HashMap.java:362)
8 [0 M  _. @) x1 A9 j; _  {( g% V$ n& tat java.util.HashMap.getEntry(HashMap.java:462)5 S+ ~. M0 _4 |
at java.util.HashMap.containsKey(HashMap.java:449)
6 H" r1 q3 t; \7 l5 B9 uat com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)
6 Z1 h3 m2 y2 B0 V- aat com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)
/ b! ?9 }: `+ r5 r7 K$ M$ T2 kat com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)
2 @: r# C1 p/ T  Eat com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)
# k- G3 ?, K$ v& B( _+ l% zat com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)
/ r& [; }) i; v! _0 v8 `  Z现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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