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

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2024-11-28 10:13:31 | 显示全部楼层 |阅读模式
java应用导致cpu占用过高问题分析及解决办法
3 j8 ?7 K# Y6 Y  }+ O
2 l' w! f! g/ G, p1 ~6 G& ]& v* N2 ?

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

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


  \$ W; y* g" E4 A4 D% H

[devops@ops_prod_flink_01 neo4j]$ jps

60226 Jps

55001 CommunityEntryPoint

8 I3 T' Q, J& h- A% F" Y0 W, K  U

[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      

/ b. f, p8 F  y( \4 S

   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

* ~6 q  [0 T7 d9 c

"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 e+ u0 k7 k8 [9 D4 b; {& e+ g6 N0 j+ s

" \5 Q+ N  ]( y% T9 Z5 ]/ B

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:22:29 | 显示全部楼层
1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。
  |! _% b/ O4 _( D9 v9 k
, L+ B" n$ j1 k: x3 j" T, h2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。
8 T* x) U1 d/ ]: j# V2 K7 d" Z7 I' _
3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.$ w& y9 W/ D5 [# v5 [6 i
" q8 Q+ g: b( d0 `' q$ L
4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了
  Y; b8 ~! G) ?9 c
; B% N$ r& [4 g8 ^5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
. f5 \+ R) V, r& Y1 l# B# m
; Q8 E% B2 l2 F1 W$ I( M1 X6.执行“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查看系统的资源占用情况9 ^! ~2 {, c4 b+ N* \
top
. U/ f; C" L. [, {" x连到生产服务器,执行top命令,发现双核的CPU几乎全被一个PID为5739的进程给用掉了,99.2%的用户空间(也可以叫用户态)消耗,极有可能是出现了死循环。( n2 j$ O+ E; _
Java应用造成us高的主要原因是线程一直处于可运行(Runnable)状态,通常这些线程在执行无阻塞操作、循环、正则或纯粹的计算等任务,另一个可能造成us高的原因是频繁GC。
8 i' A! q% C$ s; B
- }: Y  e8 w* z5 [2. 使用ps命令查看进程对应的是哪个程序3 S1 `9 u  S' t! e( d
ps
* M$ C6 {4 V9 p0 m可以看出,罪魁祸首是ccbs。这里也可以使用jps命令。
6 c4 Z8 S8 a; n! s8 p6 T# Q) f0 x# _2 b8 X- r
3. 使用top -p [PID] -H 观察该进程中所有线程的资源占用
4 @1 K, v! b& J执行 top -p 5739 -H- A& t' m3 }( J* a5 k# |7 J
top -p -H
: h, n4 y: S" c: p3 x7 p0 \, k
3 E( a* A6 A0 ^( c5 x" H$ ~参数        说明& r$ _2 @+ ^0 y7 S* x, v
-p        需要监控的进程id
* l6 q( o6 `7 [7 x-H        显示每个线程的情况,否则就是进程的总状态
+ ^. j1 `5 q/ L  A5 V0 Y发现若干线程实时CPU占用率(%CPU)较高,并且处理机使用时间(TIME+)非常长,6146线程实际占有处理机852分钟40.44秒,那么如何知道这个线程正在干嘛呢?我猜测Java这么成熟的平台,肯定有可以解决问题的工具,毕竟这样的问题很多人都会遇到。) X% i! Y: F9 U3 V+ e
: @" U/ E5 I+ P" c
4.使用jstack查看线程快照
, i# K! K6 [4 E- I9 G通过在搜索引擎中查找,我得知通过jstack可以生成java虚拟机当前时刻的线程快照。
" c) Z" o" i( `执行jstack 5739 | grep -A 100 nid=0x1802
6 R# P0 n8 }5 F# M  ajstack9 x) d4 U! b, C# t& N
jstack后面的参数是PID的值,nid的含义是操作系统映射的线程id,可以通过nid的值过滤上面占用CPU较高的6146线程,线程id需要转成十六进制,并且字母要小写。
  K6 W* q9 E% ^; X" ?6 f) p4 N通过观察输出,可以看到线程长期处于可运行状态,直接根据堆栈信息找到对应的代码。% g9 t5 m" C4 M3 J% C& Q3 G! ~

  j$ U- }% i. }* q5.解决bug
/ V. i' Z1 ]8 D0 R$ J8 ocode) U" k# U# I/ H
这部分代码并不是我写的,很明显这种写法非常不好,一旦serviceAddressType的值不在那三种范围内,就会产生死循环,我重写了这里的逻辑,问题解决。
' b+ d0 `3 ~# z/ g5 Y, ^
6 t& c% X: Z3 x6 I1 k9 B$ |4 M总结" t+ W# ?' x9 O( ~" y
任何数据都可能出错,程序逻辑应该充分考虑出现问题的可能。1 C4 Q( A. K8 y7 {& q9 _; D
我们遇到的问题,很可能别人也遇到过,要擅于使用搜索引擎。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:24:02 | 显示全部楼层
1.内存消耗过大,导致Full GC次数过多% k" B, C# G/ k# @* P/ W: O7 t+ }
执行步骤1-5:3 T/ D. ^: x, K4 g5 T* ~
$ H' h3 x8 i4 ]7 E
多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤2
) V( Q. s5 j% B通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5
6 o  r5 Q, b6 r' N确定是Full GC,接下来找到具体原因:' J$ }( L: j) c: Q( G: ]

$ `6 W% P4 j" O' i0 \# |- V生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。
! s( t1 J  [# F. W- V! v内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。1 `8 q. x1 F' V  S+ c4 v6 X7 B
2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;  }( X4 I3 A9 `* y4 x8 {% b$ x
执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。
" B# ]2 V( e% E* S+ \9 T" v% F# h1 D! L/ d
1 w4 E+ o8 I5 N9 [
% o; R" J  }8 Q" |% m2 g4 Q5 c7 ]
3.由于锁使用不当,导致死锁。( [& B& |* i% u/ L& D( h- F
执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。
( {3 P# O9 f* t8 i1 O- N' p: c1 D7 C1 b1 I
造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。* ?) K- p8 P! U  }& H" L
- j6 D# H# a9 L1 r6 c0 ?

# z0 {% [) ^+ r3 x
0 R0 M# G6 }% }% w" c3 }# H- V% C4.随机出现大量线程访问接口缓慢。
; Y- {; d0 o* v" r; k代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。
9 d$ Q# W  O6 h& I! P, T
5 X7 ^' J* d! I5 R! j思路:
( d( w0 u5 g9 Z" x6 G! F9 C8 i1 R1 c) t0 S/ w1 m3 U
首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。
/ o9 A8 O% ]" N8 v, Z# n4 D( I% N+ ~; `* v
执行步骤1-4:
9 U: t. |) s7 N0 {: h  o  G7 i$ P6 e2 T- I; Y
复制代码* u. T2 A# |( {+ Y. C3 ^  D+ ?
"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]* ^7 N7 t; v. g

1 r8 o. T6 M4 W, v  ]+ E   java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待
% _2 E- N6 b( i* K. ]* A
' |2 K8 J! p; z3 _% K6 B    at java.lang.Thread.sleep(Native Method)# t1 Y0 U* C2 \& g# f8 V, y

* S- [8 k: d0 z: f, h3 D/ x7 a$ y    at java.lang.Thread.sleep(Thread.java:340)
9 M0 _8 }: l. o7 O& @8 ]2 F4 O
9 K- ]5 Z7 {0 o  ?    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
+ A6 v5 Z1 _# [) E' J' d5 ~. C9 l7 g' n1 }/ {7 ], c
    at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点/ c* @2 S) g" b
复制代码
2 \: M& Y' G+ ]( v4 n0 j" c如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。关于线程状态,不理解的飞机票:Thread类源码剖析' n* ~$ E  A, m1 E
( ?* [9 ?* c  F! b: \
5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;
, d0 x2 o9 p7 t( K执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。% n$ y& I% h, T! q  r

& L8 h! }: G1 G2 P复制代码
, P9 k  a& t+ S, D& h+ ]  q"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]   : D1 e2 S! d  Z2 p! K& k  F
java.lang.Thread.State: WAITING (parking) ->无期限等待- ~( U* E3 r& G( U3 k$ a  S
at sun.misc.Unsafe.park(Native Method)    5 ^6 s- }7 c, U! E: _
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)    6 V% q% a* t0 O
at com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点* @7 \7 S% b/ x! D; W0 w/ _4 i; E
at com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)   
  z8 x/ e9 v$ q! Y0 eat java.lang.Thread.run(Thread.java:748)
5 o: [7 I# m% f: Y0 V- O8 f1 M- p9 w% G. z复制代码
) l9 \* Z, h/ j9 H

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-11-28 10:25:16 | 显示全部楼层
问题( J3 L1 f* x$ ~6 z* j4 A3 x9 o3 }0 O
1、无限循环的while会导致CPU使用率飙升吗?
/ |; F3 E1 h5 n$ {* D1 f2、经常使用Young GC会导致CPU占用率飙升吗?
3 L. z- R1 e2 |3 |: ~3、具有大量线程的应用程序的CPU使用率是否较高?; \, u0 g* ]# ?3 W, V8 ~/ r8 a
4、CPU使用率高的应用程序的线程数是多少?
6 S3 w, m+ z% x# y6 p& j5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?% }1 |9 L+ E- I6 k0 l% n+ H
6、分时操作系统中的CPU是消耗 us还是 sy?
5 y& C4 i) x: m0 v1 ?" J/ |7 m
) {- @3 N( W! |3 j( h思路( _0 M7 `9 x9 ]! |! M4 L7 g
1.如何计算CPU使用率?- o3 j& E  X; a* h0 v, |
CPU%= 1 - idleTime / sysTime * 100% K3 g1 J2 c1 i+ q8 ~) W9 l

6 s! e8 K/ z3 b& q& S5 h. ridleTime:CPU空闲的时间  H* K$ f7 x$ r

' i" J# L5 w; F9 U- OsysTime:CPU处于用户模式和内核模式的时间总和, @" `/ M" c+ e6 [  t

; r7 U/ T+ ^/ Q2.与CPU使用率有关的是什么?4 U& ~/ D$ t6 H9 e) y
人们常说,计算密集型程序的CPU密集程度更高。
8 |% I5 `. O8 x8 u' H' X$ a7 {3 R0 o# o2 H3 n7 P7 ~5 o9 m
那么,JAVA应用程序中的哪些操作更加CPU密集?9 A& s1 H1 m$ A0 @( C2 M5 t8 s; n' \# a
- V4 j" `. s. D8 j( O3 m# V
以下列出了常见的CPU密集型操作:+ M$ L# q8 G4 \3 N% `

1 A/ O8 t* j& t5 [2 n1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。
/ X1 \- O0 N. Z. Y1 v2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。
) G' x  a! Z  K9 r' a$ l9 T3、序列化和反序列化;
: ]! Z! w0 O" c4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。% E/ S4 P; B  q
5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。8 Y! t% Z( y# E( }, D
6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。
! O7 c: ]$ O# Z# D. |9 J1 }! J, q5 U( }% _: |: D+ r
3、CPU是否与进程和线程相关?
6 z: P9 s: M8 a现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。
! ~. I+ ~: J0 g4 C5 h  b
* o2 ^& ]5 N3 ^+ y* p答案* j" ]1 s  T8 s! o4 t
1、while的无限循环会导致CPU使用率飙升吗?
. \, j, l/ `: y8 @6 i+ s是。
' }; `0 O! }5 z& W7 u8 t# [% m  e1 ]# Q0 t# \3 @4 C
首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?8 L- G' X' {& N; L, q

: B" h7 M  P3 H; d. z1 s! B除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。整编:微信公众号,搜云库技术团队,ID:souyunku
% ~5 x( _! ?& X/ ~; J$ l7 Q% u. z( x  ^* q3 f
stackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?
5 c! T# Z' p, R) c
% c, P) N) C4 t* q; N: _https://stackoverflow.com/questi ... ncrease-the-cpu-use% Q: Q) W5 O: t  T) o

1 |1 T: u5 d* \0 \, X+ W2、频繁的Young GC会导致CPU占用率飙升吗?. K: ^' R! S" T3 w3 B/ l: G8 A* j
是。; p' M. H; O1 G1 W9 T2 N/ I8 B
% ^2 w; a( k  V) u2 \
Young GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。# G. k8 o" Q% }# @: X7 y( Z4 ]: J

1 [: ]& l. X* Z; V/ ]7 a2 e1 N让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。
4 _$ M2 x% Q' s: Z9 h3 e# Q; \
$ \( V! a: u, D) I9 p3、具有大量线程的应用程序的CPU使用率是否较高?
/ n' F* {3 V( e! u不时。/ t; Y' `5 N6 N0 P

, V1 b" r; Y1 ?% j如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。: ~. J8 t% P8 [
  v2 r6 U% d1 O5 N$ q1 }4 G
我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。
& g0 F$ j+ d& t& u! w7 I# y& p
  Y& g! U0 `( N但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。
. B/ r& m" e; a2 U* O* ?5 D8 t) O( X/ J
4、对于CPU占用率高的应用程序,线程数是否较大?6 t/ b% i  O" c% ~
不是。2 A% R- z9 G# L* I

% n: x0 b) t! _1 `( Q% ~* G高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。
9 M" A7 b0 h9 I  B5 m  P1 j& F1 e  O: }; |. W; N, _
5、处于BLOCKED状态的线程是否会导致CPU占用率飙升?
, u: H) k0 A& u$ X# C! c不会。4 m! ^7 D6 N% |/ e% b

( {' B0 s3 y0 {CPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。
2 L# t  h& |% B$ {6 r1 s
4 V, ^* T5 X' m! Q: z6、如果分时操作系统中CPU的值 us或 sy值很高,这意味着什么?
$ w7 o  J4 W! g  N2 i: P您可以使用命令查找CPU的值 us和 sy值 top,如以下示例所示:
6 G# _( z- v8 p7 Z+ f& e3 H: s- h! h+ s3 `' d6 T

) H; h# a7 @; n; dus:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。整编:微信公众号,搜云库技术团队,ID:souyunku8 S. p: p2 {7 N' A6 l6 n0 @& r# J

# B/ J6 O. k! M3 i# S7 E+ \# msy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。* y1 Y: Y! c( q" X  l

. A) K  O! E8 J! |经验
/ q6 K9 z! s- E8 j% m: G如何找出CPU使用率高的原因?下面简要描述分析过程。5 r+ B- |6 U( j# G0 b# |2 S/ j
4 B, ?+ J. I! `3 Z+ U7 \. T* D
如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。7 E3 j& J5 s& s7 B3 L- ]2 y
6 X8 p! S9 r1 x, u2 P
以下是一个真实案例:* ^  _$ \! a. W

( |: y1 l! D& L; s' z一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。2 }! }( ]9 z4 G, R7 _9 b8 c" t

, u! Z6 i) J7 B5 _( q
/ y+ B5 k1 T  U' Y* J" c; `) |' X进一步检查日志:1 H- U4 j8 F# c. _0 o

; Q5 L/ {% ?& }1 P: \3 |# j% f0 T代码语言:javascript
% L" g8 r8 Z) t复制
% L/ L! V: p9 }2 s3 m! g2 u' A4 ?4 u8 [onsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE# a: Y9 d+ S  M1 u- l4 ]) s: `
stackTrace:
# E0 `% D, ?2 ?' O- Ujava.lang.Thread.State:RUNNABLE
# p$ z' Z1 p: d, ]at java.lang.Object.hashCode(NativeMethod)
  h9 B0 s5 |& I$ ]at java.util.HashMap.hash(HashMap.java:362); o. r7 h4 S5 G& X! x) I
at java.util.HashMap.getEntry(HashMap.java:462)
: v& ^' U1 A0 B9 s: \& xat java.util.HashMap.containsKey(HashMap.java:449)
8 X2 h) C# Z  tat com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100). i$ O' M  F. w
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55); i# ~. N; N& Z# P
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)* h/ H) \+ L! X. b3 d
at com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28), q! g8 f; l3 J# X! t# N
at com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)
2 D3 P% R5 a1 g& }  q6 V% k现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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