易陆发现互联网技术论坛

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

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

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

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

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

x
java应用导致cpu占用过高问题分析及解决办法
. k1 l$ d0 V& O6 \- H6 p  _/ `6 X1 d

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

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

6 a) n4 J' l4 u4 Q. O6 y

[devops@ops_prod_flink_01 neo4j]$ jps

60226 Jps

55001 CommunityEntryPoint


  G9 ~5 @: B/ D! }" Y* `/ j

[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      

% Z3 ]8 @* t7 H8 A3 `, ^) n! m

   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


8 t* V3 R& j4 n$ @- X# e) `

"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 ^/ q! k; Y- O, I/ }


+ u. ?* c  L7 ]/ k! L# L0 w2 r; H3 L
 楼主| 发表于 2024-11-28 10:22:29 | 显示全部楼层
1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。8 d8 q  l8 Q$ o9 F5 F8 R# N7 v

5 }: M7 c# ?( `& s7 B, s2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。
" ?6 Q) ?$ b! S$ g/ V3 ?/ p" N
3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.' j, c" T" h7 }( A8 X: F) b9 G
9 M* j4 n" s4 s8 s) z: A7 i
4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了( Q3 Y- z, X6 t- F/ F3 x

/ l+ }7 c7 J* {) I9 ^( b5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。7 U: q1 R$ Z( I2 n" s/ g
2 m1 k5 u2 e& V6 ^+ @" J
6.执行“jmap -dump:format=b,file=filename 进程ID”,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多,飞机票:Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙;
 楼主| 发表于 2024-11-28 10:23:21 | 显示全部楼层
1. 使用top查看系统的资源占用情况# N/ Q' D' u9 J
top  |. |0 x- M* m4 J
连到生产服务器,执行top命令,发现双核的CPU几乎全被一个PID为5739的进程给用掉了,99.2%的用户空间(也可以叫用户态)消耗,极有可能是出现了死循环。5 M$ o, d6 Z1 [6 B  h
Java应用造成us高的主要原因是线程一直处于可运行(Runnable)状态,通常这些线程在执行无阻塞操作、循环、正则或纯粹的计算等任务,另一个可能造成us高的原因是频繁GC。
. I9 [; u- V4 H" ~
) B3 ~  v' m# s5 e9 }0 |- g2. 使用ps命令查看进程对应的是哪个程序. f+ Q+ q/ i: W4 W
ps
% [: L! S' T! ?! z. M6 P7 h可以看出,罪魁祸首是ccbs。这里也可以使用jps命令。
; e3 M1 F. e% r# n3 m: I8 K7 J
3. 使用top -p [PID] -H 观察该进程中所有线程的资源占用
2 Y+ F% f! Y" B! y; u0 c& T执行 top -p 5739 -H
, a, P! N* Z( z# U7 z( C1 Ztop -p -H& C$ W; M  c! C1 C' e

' `& {/ b% w: Y参数        说明0 G0 X4 e& M, v
-p        需要监控的进程id
7 j, X" b3 P* H  k- x-H        显示每个线程的情况,否则就是进程的总状态
. v0 a3 n, }9 Q1 [% [, k7 H! d/ {发现若干线程实时CPU占用率(%CPU)较高,并且处理机使用时间(TIME+)非常长,6146线程实际占有处理机852分钟40.44秒,那么如何知道这个线程正在干嘛呢?我猜测Java这么成熟的平台,肯定有可以解决问题的工具,毕竟这样的问题很多人都会遇到。
# j+ X3 d  o: }
1 I6 p. {0 y) X; e( m. n4.使用jstack查看线程快照
4 @, L. x* M# k/ O通过在搜索引擎中查找,我得知通过jstack可以生成java虚拟机当前时刻的线程快照。& t/ N/ z: Q$ m( I
执行jstack 5739 | grep -A 100 nid=0x1802# d6 s9 f! n2 V+ x  T7 c
jstack
1 j, N$ L1 k% ~2 H5 ]4 E1 Ijstack后面的参数是PID的值,nid的含义是操作系统映射的线程id,可以通过nid的值过滤上面占用CPU较高的6146线程,线程id需要转成十六进制,并且字母要小写。! z  v3 E; y$ C7 j# A
通过观察输出,可以看到线程长期处于可运行状态,直接根据堆栈信息找到对应的代码。
  e7 q. D& }+ ?
" N6 g& [) e. C3 s& n0 r. D# u5.解决bug
" u% g" |% g( G: Dcode6 E. E$ G. b3 Q: g: e) v! m
这部分代码并不是我写的,很明显这种写法非常不好,一旦serviceAddressType的值不在那三种范围内,就会产生死循环,我重写了这里的逻辑,问题解决。: l. y1 w5 S& }& {
! u: [# g1 I: J' _& E: F7 N1 ]( ?
总结
7 R# ^4 ~1 R9 I1 `% @/ v5 M9 G任何数据都可能出错,程序逻辑应该充分考虑出现问题的可能。8 L$ U* S0 a  G5 V; s% |) C& d
我们遇到的问题,很可能别人也遇到过,要擅于使用搜索引擎。
 楼主| 发表于 2024-11-28 10:24:02 | 显示全部楼层
1.内存消耗过大,导致Full GC次数过多
# V- |1 l1 ~5 N5 z; N执行步骤1-5:
# o7 `3 H; ^: c+ p5 c) }
% k, V1 f# I6 `5 W( Y6 Y! F  ^多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤27 }' X6 y/ I% D$ d. h; G8 f
通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5
! q0 o% O3 D6 L) T# N* H8 E0 z' U确定是Full GC,接下来找到具体原因:
7 P. ~( F4 A: }- `
  K  i! _# L. O8 T2 n( |生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。
2 D3 S3 `' |$ E3 n内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。  n( A, ^7 ?+ r1 {# @, h! x- {
2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;) }! A) \, z/ K4 U0 W2 H' W
执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。* A+ }, @- K7 n0 b" i+ W
) J2 T+ c3 w) _1 O
# |  j) A; v& I$ U1 o: c6 {: q; F

- w; J& O' A/ ~( T8 T3.由于锁使用不当,导致死锁。$ L2 Z: O- {: l3 m  `
执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。
( A1 u9 a7 H: O/ t3 x( ?. L) z; y( a& i' [; f9 K1 ~
造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。7 F1 k' Q2 h% c! e

: }: Z+ u5 W5 b4 `8 U5 G. j
! N9 G7 m3 \# R( C3 @; H
+ D& c# y2 \+ @& y/ I/ e4.随机出现大量线程访问接口缓慢。
  g. o4 N3 [$ P1 g- Z  Y# i代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。
1 T6 \% i' K' R: m! F$ [% m4 G2 c" d- I: I  J( }" n+ v6 H
思路:( w6 D8 o: v* ?

$ S9 N$ C( I" V% i" r! f首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。0 j. F3 [/ C) D( H* P# b. z' S
8 }+ V4 Z- w# e# t  h0 B( K3 s
执行步骤1-4:
' @& N1 o" }( A* }4 [9 l  W2 i
- t! c" ^: n- @4 M/ e0 \  u8 U, _复制代码* b# j% w9 H3 R% ~; F2 G5 h# ?
"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]
+ [* @$ J4 d* `$ V; I. O: y* ]# N! ]6 [
   java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待8 b3 W) G* M. x
# K4 p" U; m! a) Z7 w8 O
    at java.lang.Thread.sleep(Native Method)
5 U2 a; R- m- e( E$ X) I1 ?/ T; D+ y$ s: A3 U3 }, E
    at java.lang.Thread.sleep(Thread.java:340)
% S" k& n; H) \# ~+ l, M' E# ]/ ]7 x2 ~* @
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
. c4 H- M: b' c
1 f' @+ \) ^0 K# ~! n5 Y4 l    at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点  C1 ^/ C2 k$ A2 J
复制代码
* p4 M5 k. C# x8 g5 i' B* \如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。关于线程状态,不理解的飞机票:Thread类源码剖析- M3 M* N5 q. b+ x) m9 a+ Z

. c0 \7 y) p- x# H0 j& R* g5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;6 q7 u6 Q6 u" t+ P# e, q
执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。% k2 k5 G* W; Z  D/ f

% U8 }0 x2 j# c' d  _复制代码. H# u+ a/ t. ^4 M1 B9 v$ E- x1 {3 o
"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]   0 l( @/ |& x! t# D7 V
java.lang.Thread.State: WAITING (parking) ->无期限等待4 I9 o" ^3 H7 }/ R8 }
at sun.misc.Unsafe.park(Native Method)   
4 c$ x; c, f. Y0 D3 Q# vat java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)    2 f. ]2 m: G5 C" Y: a
at com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点/ ~8 E7 t$ ^; E( |4 s
at com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)    # O8 D8 [) f8 S2 P9 G
at java.lang.Thread.run(Thread.java:748)8 \5 k# @$ ~; Y8 q( g
复制代码( }7 F/ G1 v$ b; Q7 H0 d& d
 楼主| 发表于 2024-11-28 10:25:16 | 显示全部楼层
问题" s" l% M9 I/ V. @( t3 W
1、无限循环的while会导致CPU使用率飙升吗?) @9 \9 K5 s! f/ m& i3 W$ J1 _
2、经常使用Young GC会导致CPU占用率飙升吗?5 {; S& \( ?* [/ S6 }- m
3、具有大量线程的应用程序的CPU使用率是否较高?* Z6 c+ }. f) T$ Y/ b
4、CPU使用率高的应用程序的线程数是多少?# t- x5 |" E1 l8 ], z
5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?
7 x$ C- x6 J' g0 z9 C. I6、分时操作系统中的CPU是消耗 us还是 sy?
1 C/ G; D% _; \6 X/ S# K/ u% e+ i
思路9 g: i) d, K" n  ~9 k2 r0 K
1.如何计算CPU使用率?
. |: Q+ d/ j& P, ZCPU%= 1 - idleTime / sysTime * 1001 I( m0 Q9 u: Q+ l4 Z
( ~$ Q; R& d$ N* c$ Y1 k) [! P
idleTime:CPU空闲的时间
0 x% E: F) ^4 m* p
6 q! B  l2 x6 p+ ?sysTime:CPU处于用户模式和内核模式的时间总和
8 a* L& f  o) q
. Z3 c. e* a& C0 ^+ }2.与CPU使用率有关的是什么?6 K8 M5 K; h( t: I6 x
人们常说,计算密集型程序的CPU密集程度更高。
, c% ^' @  V' h+ z. |$ `) K9 {4 R$ I% N9 W9 p0 i
那么,JAVA应用程序中的哪些操作更加CPU密集?
% m$ ~4 u, m. w/ c$ t  R
( N7 L7 y6 @/ j6 {2 y9 T$ V以下列出了常见的CPU密集型操作:
$ P( u/ h# V% P2 ^  L# @% j  [3 K4 H; }2 l3 T! m
1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。
& I0 R9 j7 X5 G% s0 N8 Y5 N2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。' {+ ]6 c, J; ~3 m' @# P# l( u
3、序列化和反序列化;
, [( J6 j8 ^1 u( j4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。9 V/ X0 r; G" F0 g
5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。( c& {* }. \. j5 P
6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。
' ^  E# F/ r# {7 a$ d0 u
8 {1 h* a8 \+ c/ G8 s2 B( W  |3、CPU是否与进程和线程相关?- o' E4 J9 u  t+ A' h  e8 u
现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。( p& h. }; E0 y4 D! r3 {7 }
; u6 E) D, h/ n8 b0 m/ ?( e
答案
  G. C7 i* [. d) U' d* i5 }$ B1、while的无限循环会导致CPU使用率飙升吗?
0 o% k; S* I& Q5 [6 |8 R; B是。
8 F8 M/ @1 c- h& q1 R; `! T, [: S& g
首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?
8 F3 X( I$ t0 l' R9 V7 h: ?/ Z4 y# S$ Z0 U2 m
除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。整编:微信公众号,搜云库技术团队,ID:souyunku
! c' i4 z5 V# A1 k% e6 j/ N4 H9 a5 G6 U, _
stackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?9 x% H/ N: F% I% Y
( F6 u4 q7 Y# j0 m1 i- J
https://stackoverflow.com/questi ... ncrease-the-cpu-use! I% m+ m3 J: p. _& M, I

% Y7 m& @4 D, r1 n6 B$ h2、频繁的Young GC会导致CPU占用率飙升吗?
& L/ `" d1 w: Y: [( x是。
3 j  @$ |5 c3 o- j6 ]
4 C) a6 T6 R% Z3 w+ r9 }Young GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。
# Z! e% M0 E. D& m
" S7 S. d0 Y+ m; @# K让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。; V4 k/ O9 T+ q+ a+ X) ~+ z% t
5 b+ X7 `: N1 J1 k+ q+ v
3、具有大量线程的应用程序的CPU使用率是否较高?0 W  j. r. q+ P; x$ ~* ]1 _
不时。
2 @9 z3 b3 C" y  k/ y) }- `  M* K& I' T( _
如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。" y' @6 c2 F& W6 ?

$ H* P( D: l1 R8 t& }, f0 Z7 F$ B' T我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。
& a: ]4 S# A' ?, O  B' K
) C0 h, O9 t" d' }* A5 H+ H, A* I, Z2 O0 o但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。
# B+ \  V$ G% T" o3 w' e/ t- ~1 n- A( v' {3 p9 `+ k2 d  o1 g! S7 J
4、对于CPU占用率高的应用程序,线程数是否较大?
9 d) I6 s# S$ p  ^不是。9 S) S3 r1 l7 k2 h
0 K; _, G  B; U+ A
高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。
4 Q% q, I2 I9 i* k- m% q! x
4 t5 L) E+ n) k  I$ c5、处于BLOCKED状态的线程是否会导致CPU占用率飙升?
& ~' \% h0 F9 n4 k* X2 I, j不会。( I/ t7 C7 @/ a9 `' o

/ y& `9 K. Z6 R$ Y7 _, xCPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。9 l5 o$ c" @: Z. k
$ ~$ T# _- y1 `8 j6 W6 ~" {
6、如果分时操作系统中CPU的值 us或 sy值很高,这意味着什么?
$ ?' ^$ E; v" n  c3 V您可以使用命令查找CPU的值 us和 sy值 top,如以下示例所示:# ^5 n0 N( @( b. u
% f1 F, f* G5 _% Y6 g% H

; b. {: U. u( v+ a9 L1 |4 Kus:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。整编:微信公众号,搜云库技术团队,ID:souyunku( T& m% z5 b% _8 u! Z5 y
% w& F3 j! J& a. A- j
sy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。
8 R/ O9 S: H+ x# v/ ]+ a! K9 e, {9 n7 m4 J4 a
经验
2 [5 B3 C. [- W  n如何找出CPU使用率高的原因?下面简要描述分析过程。2 y/ c' S& ^1 c8 m3 j" J+ D
, |0 r- h- W) F! p# i6 {
如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。
2 c) l5 L0 e+ @7 k$ }! o5 m$ K9 f8 H1 K9 I
以下是一个真实案例:
* n, R6 k' q6 R5 D
5 Y3 i  @- f: G+ V/ M5 M/ J一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。
5 S3 N( D+ v' c4 k0 j8 l1 u: l8 {3 e0 E

! y! b9 q' C( v2 `' O* G进一步检查日志:, s( ~* E7 G5 O4 p

0 f9 @+ B0 D0 P, q1 O- z代码语言:javascript
+ M+ J3 v' i/ D, o7 H. l* `; I复制
1 I) ~; ]+ a$ C' Jonsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE
: Y2 p# z: k& ^& S4 GstackTrace:
' T' _1 n+ d8 U6 Z: _2 Bjava.lang.Thread.State:RUNNABLE" K1 v  f4 O8 b1 ~
at java.lang.Object.hashCode(NativeMethod)
1 v  d+ S7 _3 D: h+ H4 Hat java.util.HashMap.hash(HashMap.java:362)8 p4 h! @- @: D' p% _( k
at java.util.HashMap.getEntry(HashMap.java:462)
4 Y: N2 \9 K1 A, U! E9 ]7 Jat java.util.HashMap.containsKey(HashMap.java:449): S6 O8 D+ X0 R7 A$ b8 X" \: k
at com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)
; s/ h; s$ a; `+ l" f; sat com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)
" T  y4 w# @& r& K+ O9 {at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)
# P$ M$ \8 V( y. E; e$ m+ @at com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)
5 j) ^1 I, U. O' f& V8 L- U5 aat com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)2 J& z4 d3 K# G
现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

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

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

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )点击这里给我发消息

GMT+8, 2026-4-8 21:25 , Processed in 0.050940 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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