易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 28|回复: 4
收起左侧

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

[复制链接]
发表于 2024-11-28 10:13:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x
java应用导致cpu占用过高问题分析及解决办法
9 \9 @+ @5 t* \! f
" _7 c" g3 N- E! R

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

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

# D: g8 c3 u$ k# `

[devops@ops_prod_flink_01 neo4j]$ jps

60226 Jps

55001 CommunityEntryPoint


9 U0 ^! \- R& P0 [( b2 D4 ?

[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      


* a1 F. \: U0 D1 Q, w& P/ `

   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


, u% l4 N1 D3 [6 h! Q4 _* y' N% L9 V

"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

/ K7 k: g( B) y# F5 P1 N+ R: x


$ [, X2 j$ f. ~  a
 楼主| 发表于 2024-11-28 10:22:29 | 显示全部楼层
1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。& {4 E3 T2 q+ ?$ S
1 Y9 l. g. w$ g( Y. h
2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。2 d0 \4 a( u* i7 ~8 `$ [$ \
  g# X  j% R0 Z, `
3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.1 b( _8 V" P/ g+ n1 `8 m7 O

% b9 h* I6 F1 Q7 k+ t4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了
" F2 w. X/ _4 m' S
9 E* Z  `6 @  V- d) U5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
7 [) e% |) O4 ]3 G* Z+ ]
0 S% _" g9 c/ [  d; `6.执行“jmap -dump:format=b,file=filename 进程ID”,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多,飞机票:Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙;
 楼主| 发表于 2024-11-28 10:23:21 | 显示全部楼层
1. 使用top查看系统的资源占用情况
: \+ _8 l% D! w: utop! q% _) X' Z# I3 q0 c' W* e' ?, j
连到生产服务器,执行top命令,发现双核的CPU几乎全被一个PID为5739的进程给用掉了,99.2%的用户空间(也可以叫用户态)消耗,极有可能是出现了死循环。' j3 P% K5 N8 S: r; Q# i
Java应用造成us高的主要原因是线程一直处于可运行(Runnable)状态,通常这些线程在执行无阻塞操作、循环、正则或纯粹的计算等任务,另一个可能造成us高的原因是频繁GC。
% m4 t& [5 L  R; F" q$ M  R8 k* `) J
2. 使用ps命令查看进程对应的是哪个程序
$ ~. e/ [5 B: z8 U8 L, `ps
- }7 d( A& }$ s* {, E可以看出,罪魁祸首是ccbs。这里也可以使用jps命令。2 A5 b* Y+ r: P* s4 o5 T

0 w# i5 i) A+ {! o, B% {, R6 n3. 使用top -p [PID] -H 观察该进程中所有线程的资源占用
' I6 V4 C5 Z) P+ }3 l执行 top -p 5739 -H
( S( [/ e3 h- stop -p -H: E- a# k" _# P+ n7 ?# A

1 @* \) m4 G$ r参数        说明7 @) ], x% x: n. h
-p        需要监控的进程id+ ]! t: `8 R7 T- c4 f# u6 l
-H        显示每个线程的情况,否则就是进程的总状态
1 I7 o/ t& ~: Q( ]2 I/ K发现若干线程实时CPU占用率(%CPU)较高,并且处理机使用时间(TIME+)非常长,6146线程实际占有处理机852分钟40.44秒,那么如何知道这个线程正在干嘛呢?我猜测Java这么成熟的平台,肯定有可以解决问题的工具,毕竟这样的问题很多人都会遇到。
: P# _1 R+ W0 Z9 F* }
- ~3 J! o( R  p9 Z! O  r0 C4.使用jstack查看线程快照3 K6 u+ i. H# l7 {, _
通过在搜索引擎中查找,我得知通过jstack可以生成java虚拟机当前时刻的线程快照。$ G' N+ v* G- t9 v% M0 f
执行jstack 5739 | grep -A 100 nid=0x1802
+ T  p3 N9 H! s& S8 Kjstack. Z! v' u2 Z" S! S
jstack后面的参数是PID的值,nid的含义是操作系统映射的线程id,可以通过nid的值过滤上面占用CPU较高的6146线程,线程id需要转成十六进制,并且字母要小写。
( l/ C, a" N  {% n% z% M2 s' K通过观察输出,可以看到线程长期处于可运行状态,直接根据堆栈信息找到对应的代码。, B3 I# t9 [! G; B

$ E" Z8 {1 A; V5.解决bug+ x& S8 a! T, h
code( Z# G8 v( x6 X( Q4 D
这部分代码并不是我写的,很明显这种写法非常不好,一旦serviceAddressType的值不在那三种范围内,就会产生死循环,我重写了这里的逻辑,问题解决。. y$ s1 M: i9 r$ }
3 O0 I" K4 r6 H( J* P
总结1 U& z6 D+ f- Z
任何数据都可能出错,程序逻辑应该充分考虑出现问题的可能。1 H+ j% N2 E+ \1 X& ?
我们遇到的问题,很可能别人也遇到过,要擅于使用搜索引擎。
 楼主| 发表于 2024-11-28 10:24:02 | 显示全部楼层
1.内存消耗过大,导致Full GC次数过多
( p7 y; z6 O+ y# C: x执行步骤1-5:5 G' N3 `" w9 J, m3 @( `
' F: K6 l/ Q" h8 D! P1 f
多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤24 o& J% p' V1 P  m5 V
通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5
) h1 n* v9 a. C2 `7 }- B/ }确定是Full GC,接下来找到具体原因:6 w, h4 _) B* l6 D. P2 Y, C8 Q% R

9 g6 w+ w! o4 @8 ]) K! f+ B" m. b生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。: R. g" c0 p4 I
内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。
2 m  r% `3 z9 L. J6 t* _: F2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;1 o8 s* L7 {) V, [' }- h3 X6 `
执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。: O+ {% Y; w* {: q: x
( Q5 J8 ]$ f0 {1 j
1 Q, G. u7 \/ ]7 x  q7 O

1 K$ S6 \+ b6 F3 p3.由于锁使用不当,导致死锁。
5 S& V3 P% h+ d执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。% m6 N8 \* i8 d5 N6 ~9 L9 M0 b
# ^( I  T: ~3 K" h/ A3 g3 R
造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。
  }4 n2 a  q1 n1 S, q) _' C/ n6 F! d3 _# }% W. R7 \

+ r( t+ a' d+ P" I
; g% m3 B* g" z/ ]0 y4.随机出现大量线程访问接口缓慢。
. g4 p: ^; p+ C6 o5 T代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。. O' _0 U' B# i, y( V) P

/ Y; |7 I  W1 q8 p) C2 k. a* n. g思路:7 m2 Q; S4 g) `8 v( _8 f
7 g" ~, p( n  |9 C5 r( e, g# V# m
首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。
8 @! z5 I5 \4 ?& x% @& [$ t5 H8 e3 c  R; m
执行步骤1-4:: `$ q) l9 T+ P& {2 t
% p# p4 Z" y- W$ p
复制代码
  V  f; n7 H6 r& c. X"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]$ l( v! Y  q$ l- ?5 B1 Y
2 P  F: `2 W5 y, A$ \4 S7 ~8 z% q
   java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待
$ D( w. f; m7 ], P% g% v6 H' P
6 i0 \% s5 O" {7 P3 H9 G4 |- G    at java.lang.Thread.sleep(Native Method)
9 d7 M1 t1 c8 z( N0 f; N
# F1 U. Y% v5 g2 o& ]0 k3 i    at java.lang.Thread.sleep(Thread.java:340)' M/ o' j1 k( L7 O* n; h

9 X, _5 ?; Z9 ?- c# [, f' \# b* ~! `    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386): g4 n0 x: X9 Q& L

9 X6 b0 l$ W# G: d2 L, k    at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点( _4 A) S% n& F* p/ C! c: {
复制代码
5 r$ w; s. o. ^  m' {8 O2 q如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。关于线程状态,不理解的飞机票:Thread类源码剖析
4 Q* i+ p7 X+ U( \) p2 Y( x0 P: x) b0 Y3 U" b  p& B
5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;
& u7 j- ?* o# F8 |& m& b; B执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。
% z5 p7 f! h% k$ [" ?7 E# B( ~( `4 j" S% @4 W) A  r
复制代码
1 d" {9 l! O( J"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]   5 L* {; L* X/ F/ ^: n- c
java.lang.Thread.State: WAITING (parking) ->无期限等待
0 R1 g2 e% A+ C% ~3 Dat sun.misc.Unsafe.park(Native Method)    & B3 J6 u1 i1 R# R
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)   
2 {7 D4 Y/ m+ j5 hat com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点
# J3 Q) Q. P  z( S4 Mat com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)    + Y8 m* E7 G: y4 \2 `
at java.lang.Thread.run(Thread.java:748)
% k: ?2 L: p# I/ {' W7 |复制代码% x9 n* S9 }' r6 \
 楼主| 发表于 2024-11-28 10:25:16 | 显示全部楼层
问题
8 j& x( ^  m1 Z% t% c1、无限循环的while会导致CPU使用率飙升吗?6 M: d* g" s, J- \; v
2、经常使用Young GC会导致CPU占用率飙升吗?+ `# L. _) f2 D" e: Z4 b
3、具有大量线程的应用程序的CPU使用率是否较高?
1 |- j* S  @* h  n# q; R4、CPU使用率高的应用程序的线程数是多少?
! w9 g% s: E/ U1 H  |5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?4 M; C. r% n( z1 T$ t9 ?
6、分时操作系统中的CPU是消耗 us还是 sy?
5 o" k; Z+ {- f! F, W! @3 M2 ?
& m* k# K  V5 O, U* T+ I思路( ^) E0 O- v8 Q  G+ X3 J, H
1.如何计算CPU使用率?
2 D/ `' I6 ]9 s! ^! X/ cCPU%= 1 - idleTime / sysTime * 100
3 S8 X* |! ?1 ^
7 u% p* u0 n* v! sidleTime:CPU空闲的时间7 d0 r# D: X& h$ X& w

% V( v9 d% V) |) w' r/ zsysTime:CPU处于用户模式和内核模式的时间总和( T! _4 M% x$ d0 P
9 |( t+ j, R0 B7 C8 U0 v
2.与CPU使用率有关的是什么?! c2 D) K+ |$ H! @5 L# `2 s3 m  g
人们常说,计算密集型程序的CPU密集程度更高。
+ r( z5 B7 k. ~* a5 S
+ f5 }# z" k  o! p! p! i那么,JAVA应用程序中的哪些操作更加CPU密集?0 |) ~1 }0 c7 V; Q7 K9 Q

1 [. s# S. o( @: m以下列出了常见的CPU密集型操作:
6 G6 `" G( f) e$ T; K  X
! W3 |  B  O: I% K* r1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。
5 S2 o2 C" D8 L8 X; B2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。
, N9 x9 N. g0 F# p& b; O* ?0 Z3、序列化和反序列化;' J9 s6 ?2 E% W; l5 k  N. u
4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。& J# ?. W$ K+ P6 F+ G& a: B
5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。
; h# J2 ^& v% z9 s6 c6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。
$ _" o8 X0 G/ E* Q6 a8 P$ g3 q2 T( N: y$ m; V* h  p( t
3、CPU是否与进程和线程相关?
6 L, x6 s  _" v0 ~) ~现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。
1 ]- u  C9 N3 |5 s% c( b7 x3 v  D5 R  Z1 ]& \. m
答案
1 {3 l7 c7 x& B  d1、while的无限循环会导致CPU使用率飙升吗?( t7 \% A7 ]& }6 H  f# i
是。+ f* M0 C8 g* _! ?

0 v; @% ?: e# `2 |" r6 |; @" l( f4 u首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?
2 W7 K  q+ f5 F3 n* j; p
# X$ S- d, p9 j: s7 @( N& v2 R- X6 \除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。整编:微信公众号,搜云库技术团队,ID:souyunku
+ m' K) p  t: N, p5 R
" v$ ?; x2 ^$ o- Jstackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?) t# C0 @) S. x- w. c+ |
# m% U6 m% q1 ]9 Z1 x3 }( b" ?" u9 U
https://stackoverflow.com/questi ... ncrease-the-cpu-use+ {3 w; R: B  L. X- G. v

( Z8 R. b; U. n0 e* v# Q9 H2、频繁的Young GC会导致CPU占用率飙升吗?
! T) ?0 ^, F! G& s4 j是。
3 \" q- r3 a% {; e* u4 c
+ }; E  h0 \0 HYoung GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。) }3 i- r% l0 j1 z0 y2 i

5 o( [4 |3 x& q让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。
; s0 G6 B6 h9 ~' i! @- A9 W: r* r7 W$ i: l* B3 M
3、具有大量线程的应用程序的CPU使用率是否较高?$ f; _+ b: ]) p
不时。. c4 O% F6 W9 B0 ~" D! c
9 |' c# E! {2 O% E# @+ J* A
如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。
  b, x& \7 H6 e6 ]& r; E6 B4 m
* _5 X! g6 m5 w9 b3 d- _8 K我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。* s- D* z. V" k8 P- {$ l$ i

& Z9 x& m, |7 H1 N但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。
0 k9 B) c8 V7 _# R) X% J+ v. L1 x# t$ S- V% C
4、对于CPU占用率高的应用程序,线程数是否较大?
' ~6 V2 c8 A7 z# P! H不是。/ T4 T" Z) g. }+ S

$ S% c2 g" M( m& P+ W& i) z4 I* p高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。
- q- V/ O% N" u
- V# {, V8 a8 N4 `, t0 x+ n4 \5、处于BLOCKED状态的线程是否会导致CPU占用率飙升?
" b" g5 R$ ^- ]% ~. Z( y4 e不会。% {1 J- h3 m% Q6 }) D
9 ~& i( t6 w. Q1 k6 R- m  v
CPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。; Q9 f5 k6 o  J- |$ q% z2 D

* R8 |8 l5 ?1 s4 [# N$ j6、如果分时操作系统中CPU的值 us或 sy值很高,这意味着什么?
  D* W. |0 W2 {. s您可以使用命令查找CPU的值 us和 sy值 top,如以下示例所示:
5 W1 Q6 }. B. z+ a- B. I8 \  F6 f) x

) u8 Y. O+ z4 S' A4 cus:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。整编:微信公众号,搜云库技术团队,ID:souyunku) |2 v! f$ @: F) x+ M; \
# A9 F+ a9 l) L, a
sy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。9 i4 ^: h% b% G& h7 u6 \- ]

2 V3 p1 D/ F$ ~  T3 ^7 r5 V& Q) v经验
( ?% n" x5 U; \6 Y2 Y* w9 K: k如何找出CPU使用率高的原因?下面简要描述分析过程。6 x, w+ T7 _; }5 |. U, A

$ C( V/ d4 U* \如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。+ j- l% p6 j$ _7 S; t8 z4 o
% d1 B5 d8 q( d* M2 P* }. b: f
以下是一个真实案例:
" R7 \; m8 }' h' {1 i% Z& K9 t! o5 `
一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。2 q/ O' c1 |' J8 ~  z( d* {8 d

" b. I+ S$ p5 Z% d* l0 l0 O
( ]% ~" ^+ A8 I: \5 R进一步检查日志:
4 F4 k1 M$ h9 O; \. l- E; Y0 }! o, A% b
代码语言:javascript
/ u) L# _* w+ ^9 P8 \9 K复制
4 c  C' J) Z- D+ k0 R$ N5 Vonsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE
6 h' T* B/ v% P& a8 D9 }8 X% istackTrace:
1 M' q7 f( G9 z8 E! a! pjava.lang.Thread.State:RUNNABLE
4 |. X! u" t# Qat java.lang.Object.hashCode(NativeMethod). A, T5 \6 Q6 W9 I4 Q
at java.util.HashMap.hash(HashMap.java:362)+ F+ T+ C3 a, O' a9 c6 P  k& Y% N
at java.util.HashMap.getEntry(HashMap.java:462)
* Z# V1 M2 P: z, Q+ M- Uat java.util.HashMap.containsKey(HashMap.java:449)! c/ m" a7 X; P  B, q
at com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)5 u  U& z7 a4 {8 f$ z- l$ ~, X# U4 o
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)
+ y# M  K, G( _, f" Wat com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)
# n' ~; b$ r: d2 q2 |2 s0 U) w. Mat com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)
* _6 j* k3 F, h  R& R" {6 nat com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)
  a; [4 W0 D& n0 T- n1 \现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 点击这里给我发消息

GMT+8, 2026-3-9 00:33 , Processed in 0.060177 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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