易陆发现互联网技术论坛

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

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

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

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

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

x
java应用导致cpu占用过高问题分析及解决办法: w" O5 Z' {# K; G* |

" A- m! i9 K4 h* M7 Z9 M

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

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

- U! w1 v7 V0 a5 q) \

[devops@ops_prod_flink_01 neo4j]$ jps

60226 Jps

55001 CommunityEntryPoint

- S2 Z9 B1 A! j7 ^# c$ |! d* 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      


0 ~- y& Q" h8 a+ r/ k

   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

' r1 @) {: X8 [7 M4 C& l& s, u9 ?

"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


- X  S, e1 @# |


0 j6 D7 S. h6 j  ~# O, Z
 楼主| 发表于 2024-11-28 10:22:29 | 显示全部楼层
1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。. U0 w% D+ V0 R5 m. O

) t/ p5 v6 p. S: r' Q2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。
& f, ~5 M% I  E( ~7 A+ v' M
8 E+ j% O0 R3 s( r9 K. c3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.
" \! V. l3 ?2 C
8 r4 ^1 B9 K: A$ C5 _# y* Z4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了+ U+ ~0 C) O$ t0 W- ~0 f* W

! l$ o5 l" `( h  a9 ~" `6 E5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
# n/ c8 A; a+ b6 V. X1 K9 m9 n! d* U- }6 A
6.执行“jmap -dump:format=b,file=filename 进程ID”,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多,飞机票:Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙;
 楼主| 发表于 2024-11-28 10:23:21 | 显示全部楼层
1. 使用top查看系统的资源占用情况; H- ?% j# `/ e
top' C0 e2 X4 |# |1 f1 \1 ^6 B" W/ A
连到生产服务器,执行top命令,发现双核的CPU几乎全被一个PID为5739的进程给用掉了,99.2%的用户空间(也可以叫用户态)消耗,极有可能是出现了死循环。
) @) g$ B1 _! P- h6 g. gJava应用造成us高的主要原因是线程一直处于可运行(Runnable)状态,通常这些线程在执行无阻塞操作、循环、正则或纯粹的计算等任务,另一个可能造成us高的原因是频繁GC。
( A0 b. }. a0 h4 ]) Y4 Z) ], a2 {9 v* z% B. k) a/ \# T6 f$ f
2. 使用ps命令查看进程对应的是哪个程序' X! b( K7 s  E/ ]) F
ps
/ v( N/ ], O+ I$ F2 w! s可以看出,罪魁祸首是ccbs。这里也可以使用jps命令。6 b  d/ u! z9 u) L% x! a9 z
! ?# k6 D8 B4 `1 v
3. 使用top -p [PID] -H 观察该进程中所有线程的资源占用
4 i3 `( ]( `% L* c执行 top -p 5739 -H
9 L. f+ o: y/ K. V, Vtop -p -H
4 Z" D9 {. y8 ], B% Q. {( S4 r9 a; V- s- E
参数        说明# T& T: C% A  ~# u2 [
-p        需要监控的进程id3 u9 P+ E& l" ~& e- j- ~/ R% @
-H        显示每个线程的情况,否则就是进程的总状态
. j5 C+ c% c* x3 `发现若干线程实时CPU占用率(%CPU)较高,并且处理机使用时间(TIME+)非常长,6146线程实际占有处理机852分钟40.44秒,那么如何知道这个线程正在干嘛呢?我猜测Java这么成熟的平台,肯定有可以解决问题的工具,毕竟这样的问题很多人都会遇到。$ L( x# w8 S% ^# N1 }) M4 j
: j: l+ X2 r- i3 a0 ^
4.使用jstack查看线程快照
) t. o  V) i4 u7 l; m$ I通过在搜索引擎中查找,我得知通过jstack可以生成java虚拟机当前时刻的线程快照。- U% [2 g! T) O# j6 ]
执行jstack 5739 | grep -A 100 nid=0x1802, m4 A( o" e7 w1 g
jstack8 N/ j9 ~, N  g. y* _, k( ^8 ^( k
jstack后面的参数是PID的值,nid的含义是操作系统映射的线程id,可以通过nid的值过滤上面占用CPU较高的6146线程,线程id需要转成十六进制,并且字母要小写。$ b6 k1 G) i4 |7 g0 X* t9 S1 h$ w
通过观察输出,可以看到线程长期处于可运行状态,直接根据堆栈信息找到对应的代码。. S7 B. S" I3 F
8 S0 n- ]) s! G( P
5.解决bug
8 R# H4 A6 W2 q. ^8 tcode
6 \6 ?! x% G$ d" J这部分代码并不是我写的,很明显这种写法非常不好,一旦serviceAddressType的值不在那三种范围内,就会产生死循环,我重写了这里的逻辑,问题解决。
1 u% Q/ ?: _. ?1 ?( u6 V
9 g3 A) N% M) r& [% g: G. S总结
2 c& u) V2 \4 g  I5 G) S' w3 U7 S任何数据都可能出错,程序逻辑应该充分考虑出现问题的可能。
4 Y& j& X2 n* a2 K: {" T我们遇到的问题,很可能别人也遇到过,要擅于使用搜索引擎。
 楼主| 发表于 2024-11-28 10:24:02 | 显示全部楼层
1.内存消耗过大,导致Full GC次数过多
' i' J$ S& P' j( ~执行步骤1-5:
- o6 h8 h8 R8 a( P" g: B
. X( @  y2 h2 j, p) v多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤2
% C7 R7 V' z9 ]. D  }* A通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5& K  p3 b2 h$ \# y# ^
确定是Full GC,接下来找到具体原因:
3 ~! N- B6 t2 p/ C" ]6 t8 c$ p9 r
生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。
- _) K' q. l5 C' S/ J5 @内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。( n# n3 X9 @  W$ ?( T8 B
2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;" c0 C, ?/ B8 `
执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。
# Q+ a8 G1 l( {3 S0 e# F# e$ N5 Y# ], P' Z9 y
4 M" s& H3 `3 ]4 K2 q( `4 A2 q

8 C6 g9 f; o# s+ I  f% ^3.由于锁使用不当,导致死锁。
2 b' B+ y( A" ^( U# G& c执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。' p. v9 O4 a: Q0 ^
4 P: g1 @, x1 E% d1 }9 {) A* G
造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。
' r* A' D7 `4 P) k; o6 J, i0 b8 |' C' K' ~6 g# G3 q! G: T
/ o, q4 L: ^0 P" t  h6 V* U
4 [! O1 {2 m+ ~, O  E5 Q
4.随机出现大量线程访问接口缓慢。
/ Z" M2 c7 ]! o# |4 \代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。
# Z+ A5 \+ F. _7 w; @- A
0 E' P7 R; t0 ~, ?1 T& l* T思路:6 D! @7 `$ ?# ]/ ~
9 I. i. Q5 B( X8 f/ y; ?- o! Y
首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。
1 E/ ]/ O. V9 j6 R
+ A1 o; `- K3 J( j: i执行步骤1-4:/ E7 M9 M3 C8 G/ y5 V& a
' ]1 `1 i% H# A  o7 @% j% v
复制代码& t, x" a! n7 k
"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000], Q( u  J* Z( U' q
, o0 h* h+ t! b
   java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待
' i- h: t8 x/ p7 v
" h8 e- p2 [8 M" k: i1 ^; o: R1 s    at java.lang.Thread.sleep(Native Method)
, _, d" g- ]; a1 C  D. O0 Z/ q4 J9 f: ]' H
    at java.lang.Thread.sleep(Thread.java:340)
5 P2 ?% ]! V  o9 R8 P. d& v  Z8 N
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
* G  ^5 L& r( ?- M- \" x2 o
% T. r2 L: c, [  n( n2 |    at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点
  C( |' J/ E! k/ `复制代码
# u) y0 ]: x* v% Q如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。关于线程状态,不理解的飞机票:Thread类源码剖析
4 M: Q# [1 U, o, T9 X' u5 ]# ~% z# ~; `- [/ o# R( K+ U
5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;
& T1 f  f) J& u, y# U* l执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。; P3 ^/ s/ ?4 k3 n
- X. ?2 V& n1 y
复制代码
6 e$ d0 h" z0 v2 Z! W"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]   7 |3 _* R- `" }5 |, j
java.lang.Thread.State: WAITING (parking) ->无期限等待
! @( h1 o2 H/ Cat sun.misc.Unsafe.park(Native Method)   
/ H( T9 E/ V; g( M- D* Jat java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)   
" m, \) b4 A0 Z. O3 @at com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点& e- n" U) A4 f
at com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)      u4 o3 ]5 [3 Z8 m9 J) ?
at java.lang.Thread.run(Thread.java:748): o! b* G, a  z  }, _2 N0 ~. |  J* S
复制代码6 X9 A1 h. x) y/ K
 楼主| 发表于 2024-11-28 10:25:16 | 显示全部楼层
问题
, {+ X  o8 r- t& K# f1、无限循环的while会导致CPU使用率飙升吗?7 O! `0 Z2 \" a
2、经常使用Young GC会导致CPU占用率飙升吗?
+ k! n; @2 D# D$ g) `3、具有大量线程的应用程序的CPU使用率是否较高?4 {2 s8 J" b  O: D
4、CPU使用率高的应用程序的线程数是多少?6 q  P( E" w" o1 T# F
5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?$ }2 F& ^7 ?- ~* j- s
6、分时操作系统中的CPU是消耗 us还是 sy?
; w/ H5 r6 b+ h$ a- Q* d/ b0 I" J) d, a  i: }% b% H$ X+ g7 Z
思路; m2 \+ }+ S/ A/ ?% k* C$ u" D
1.如何计算CPU使用率?( e% p% _5 V; G  a- c" m5 k. }* w
CPU%= 1 - idleTime / sysTime * 100, {8 d- V, x& D/ y- [5 A

  ?  \. B; z3 E  q/ H" @8 [* hidleTime:CPU空闲的时间
  `3 Y; s& k% M" A, E
: s  T/ L% U- X$ A2 r! ~$ O" S' DsysTime:CPU处于用户模式和内核模式的时间总和
4 u4 A4 D. Y6 c& }9 [
& n( ^/ T9 N6 a+ ]3 q2.与CPU使用率有关的是什么?% _1 N  ?/ I! N+ w; p3 [3 \
人们常说,计算密集型程序的CPU密集程度更高。
( X  n' y& T3 n* z
) G6 b: p' L& }" o) \" c那么,JAVA应用程序中的哪些操作更加CPU密集?6 ^% y. i: ?; x! i8 j& r4 s% o

. w6 \8 k! ^5 w. X" s以下列出了常见的CPU密集型操作:, E3 N% `0 j8 r; Y& E" a

- I+ ^2 `4 T4 d9 Y. T5 t# p1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。
7 w1 n  z; |1 E- Y2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。
" L# H( ~+ S4 a) ~7 T3、序列化和反序列化;; T( T4 k0 T! w  X! Y! i. h% W
4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。
' H: Z% J$ q/ F) m/ R2 i5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。8 K7 O" ~" O- [0 F( G
6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。
: w9 n$ V- {: ?$ Z; @3 T; T5 Q& ?2 P  R& F9 @
3、CPU是否与进程和线程相关?
4 n) d/ w1 F" _7 l现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。. P( j# s! K9 B5 i2 T! F

$ _3 V1 b" I& x; S! Z答案& l) a: Q" |+ v1 ]
1、while的无限循环会导致CPU使用率飙升吗?0 d5 d& z* K/ @6 C1 v$ ~
是。
$ }. y0 X/ d  K( g$ ]" t
2 r- _, j) [8 B+ z首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?
2 _5 g( g- B5 f0 p
0 {( \) n: c, ]7 i: s( s: w除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。整编:微信公众号,搜云库技术团队,ID:souyunku
. c8 J- Z, \. C/ n/ p7 F9 f/ W9 V; ^8 D, y' c& W  v9 M9 x5 h% b
stackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?
( Q7 W7 _: R/ j" P1 _3 F5 ~" |" r2 Y
3 R& f7 C: v$ z: P$ R) A0 N3 O* ghttps://stackoverflow.com/questi ... ncrease-the-cpu-use
! \; e0 i- W  J2 b7 a
: o9 H# P/ t& Y- c! r" Y2、频繁的Young GC会导致CPU占用率飙升吗?- L4 Y/ B/ c. f  E  P5 Y9 y
是。0 f4 d' |' {9 t) r1 b" Z. R9 T

, _' L# z* G. m5 Y1 V; C8 o# y8 p( [Young GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。
0 K: [. H$ T: u$ C3 B+ I9 \- P4 u. L; p/ c/ ^
让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。( v. P$ G2 |1 s4 E; e
6 n+ v; V/ g% K% t5 t+ p
3、具有大量线程的应用程序的CPU使用率是否较高?" j- X6 b  b  G& @
不时。( T, \" d, f- E& G* b& H4 ~, L
* Y- j6 }8 k) C' T# `
如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。/ r/ Q) ?9 q' z

, h4 I. B2 Q# o) b4 ]) B我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。
8 {2 Q2 i: b: i3 a6 k$ A
! e. l7 @0 A/ s但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。
2 J, T" l2 B- s6 `: Q
6 ^5 z8 P7 ^$ m# ~( N7 C$ Q8 @' K4、对于CPU占用率高的应用程序,线程数是否较大?
# g* ?+ `$ T9 L- L" w* X不是。
0 c$ W9 L4 G# T! y# B5 [1 g. S/ k5 G+ t
高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。" \+ |" B; E% Z7 c" X( L# O( o- i

- F% E0 F2 U9 S, o5、处于BLOCKED状态的线程是否会导致CPU占用率飙升?3 u" q4 v" ~! [4 I2 [- m
不会。  M5 h% U# t  R: g
6 T& M' S7 i0 n9 ^3 O; E+ L7 h
CPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。! X( v$ G4 C6 d* L6 F3 v( \
; F8 }) j  s$ F
6、如果分时操作系统中CPU的值 us或 sy值很高,这意味着什么?# h8 b4 ]  _' p: Y. K
您可以使用命令查找CPU的值 us和 sy值 top,如以下示例所示:
5 a: U, m2 M6 @6 C
* Y7 k, h9 ?: A
( Q: d/ r. ]9 }us:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。整编:微信公众号,搜云库技术团队,ID:souyunku- I8 h1 u7 D6 D8 H

  M& z$ a& ?+ |2 M5 C5 N" asy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。9 N8 \3 H  }5 C' ?
  ]9 G, Q; V# C$ J* b0 [) K
经验
5 U: K+ q: R* ~/ i& q如何找出CPU使用率高的原因?下面简要描述分析过程。
2 @  b, R/ r; d% d2 a  V  V: e- I" N- `
如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。
, {2 _7 [1 o$ c1 J2 V* v
+ U& D- N6 c& T3 \0 P; |# b6 v以下是一个真实案例:
  }* F2 |$ F: F0 l0 e8 L+ N2 H/ d
一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。0 x& B0 _3 g+ s( J0 R' t6 v
# f1 a. T7 A& ~, B6 R: |$ J
2 A) }2 M% J: D
进一步检查日志:
9 o: E8 }8 Y2 T5 U' {$ V$ [, |+ t; H0 J0 @3 H
代码语言:javascript
( R1 U# Z6 i& i3 B复制7 m- x* v% I/ W6 n1 s$ Z) c
onsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE) N5 a, I: \2 d0 {
stackTrace:
, c  z9 i4 L' z. `5 Ajava.lang.Thread.State:RUNNABLE
% B/ E/ E% z& H: ~* Q5 |at java.lang.Object.hashCode(NativeMethod)8 ~, c/ ^' ~3 F$ r
at java.util.HashMap.hash(HashMap.java:362); n- I4 [3 q: ^, i' W
at java.util.HashMap.getEntry(HashMap.java:462)  b6 E0 u* H  _1 Z
at java.util.HashMap.containsKey(HashMap.java:449)
7 E& }: I" g! \) `2 M* S- Dat com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)
7 `* X- |) H" r4 H& i' n+ ]7 u& U/ gat com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)8 S% q1 p) _7 |# @
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)6 y  e$ v6 F( s% Z, c0 P( i  U8 D
at com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)
# ?) }' ~; E3 M2 |5 R/ O' y" M0 [at com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)
  q9 T# ~' S: i( i- k现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

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

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

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

GMT+8, 2026-4-8 15:50 , Processed in 0.090312 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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