} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},“t1”);
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (b) {
try {
Thread.sleep(3000);
synchronized (a) {
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},“t2”);
t1.start();
t2.start();
}
}
启动前
没有启动任何JAVA线程,CUP占用为0%
启动后
我们发现CPU被打满100%。进程为我们启动的程序。这个时候我们肯定想知道线程都在干什么。导致CUP消耗过高!那么具体怎么排查呢?
2、问题排查
获取进程ID
通过top命令可以看到,最消耗CUP的进程ID。如上图,得到进程ID为3030
查看进程内的线程ID
得到进程ID之后,我们可以通过
top -Hp 3030
命令查看进程内的线程ID,如下,找到最耗CUP的线程ID3051。
将线程ID转为16进制
printf “%x\n” 3051
jstack命令查看线程执行情况
通过java自带的jstack命令导出栈信息。发现是busyThreadName线程在执行。查看代码发现死循环,导致CUP100%。
jstack 3030 | grep beb
二、show-busy-threads 脚本
======================
但是每次查找都要执行那么多命令实在有点麻烦,步入我们就整合一下,把查找过程放在一个脚本里,岂不是美哉。
代码如下
#!/bin/bash
@Function
Find out the highest cpu consumed threads of java, and print the stack of these threads.
$ ./show-busy-threads
#ARGS= -p pid
#[ $? -ne 0]
PROG=basename $0
count=3
redEcho() {
[ -c /dev/stdout ] && {
echo -ne “\003[1;31m”
echo -n “$@”
echo -e “\0ee[0m”
} || echo “$@”
}
if ! which jstack &> /dev/null; then
[ -n “KaTeX parse error: Expected 'EOF', got '&' at position 14: JAVA_HOME" ] &̲& [ -f "JAVA_HOME/bin/jstack” ] && [ -x “$JAVA_HOME/bin/jstack” ] && {
export PATH=“ J A V A H O M E / b i n : JAVA_HOME/bin: JAVAHOME/bin:PATH”
} || {
redEcho “Error: jstack not found on PATH and JAVA_HOME!”
exit 1
}
fi
uuid=date +%s
_KaTeX parse error: Expected group after '_' at position 9: {RANDOM}_̲$
cleanupWhenExit() {
rm /tmp/${uuid}_* &> /dev/null
}
trap “cleanupWhenExit” EXIT
printStackOfThread() {
while read threadLine ; do
pid=echo ${threadLine} | awk '{print $1}'
threadId=echo ${threadLine} | awk '{print $2}'
threadId0x=printf %x ${threadId}
user=echo ${threadLine} | awk '{print $3}'
pcpu=echo ${threadLine} | awk '{print $5}'
jstackFile=/tmp/KaTeX parse error: Expected group after '_' at position 7: {uuid}_̲{pid}
[ ! -f “${jstackFile}” ] && {
jstack ${pid} > ${jstackFile} || {
redEcho “Fail to jstack java process ${pid}!”
rm ${jstackFile}
continue
}
}
redEcho “The stack of busy( p c p u {pcpu}%) thread( pcpu{threadId}/0x t h r e a d I d 0 x ) o f j a v a p r o c e s s ( {threadId0x}) of java process( threadId0x)ofjavaprocess({pid}) of user(${user}):”
sed “/nid=0xKaTeX parse error: Expected group after '^' at position 16: {threadId0x}/,/^̲/p” -n ${jstackFile}
done
}
[ -z “${pid}” ] && {
ps -Leo pid,lwp,user,comm,pcpu --no-headers | awk ‘$4==“java”{print $0}’ |
sort -k5 -r -n | head --lines “${count}” | printStackOfThread
} || {
ps -Leo pid,lwp,user,comm,pcpu --no-headers | awk -v “pid=${pid}” ‘$1pid,$4"java"{print $0}’ |
sort -k5 -r -n | head --lines “${count}” | printStackOfThread
}
此命令通过结合Linux操作系统的ps命令和jvm自带的jstack命令,查找Java进程内CPU利用率最高的线程,一般适用于服务器负载较高的场景,并需要快速定位导致负载高的原因。
本脚本来自一个叫候鸟树的网友,原作者不详,这里保留原作者名为了表示对技术人的尊重,在他的脚本的基础上做了一些改动。
命令格式:
总结
总体来说,如果你想转行从事程序员的工作,Java开发一定可以作为你的第一选择。但是不管你选择什么编程语言,提升自己的硬件实力才是拿高薪的唯一手段。
如果你以这份学习路线来学习,你会有一个比较系统化的知识网络,也不至于把知识学习得很零散。我个人是完全不建议刚开始就看《Java编程思想》、《Java核心技术》这些书籍,看完你肯定会放弃学习。建议可以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。
来自一个叫候鸟树的网友,原作者不详,这里保留原作者名为了表示对技术人的尊重,在他的脚本的基础上做了一些改动。
命令格式:
总结
总体来说,如果你想转行从事程序员的工作,Java开发一定可以作为你的第一选择。但是不管你选择什么编程语言,提升自己的硬件实力才是拿高薪的唯一手段。
如果你以这份学习路线来学习,你会有一个比较系统化的知识网络,也不至于把知识学习得很零散。我个人是完全不建议刚开始就看《Java编程思想》、《Java核心技术》这些书籍,看完你肯定会放弃学习。建议可以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。
[外链图片转存中…(img-E7XHSSn2-1714304221550)]