一文学会Java死锁和CPU 100% 问题的排查技巧

作一个积极的人html

编码、改bug、提高本身java

我有一个乐园,面向编程,春暖花开git

工欲善其事,必先利其器github

 

 

00 本文简介

做为一名搞技术的程序猿或者是攻城狮,想必你应该是对下面这两个问题有所了解,说不定你在实际的工做或者面试就有遇到过:面试

第一个问题:Java死锁如何排查和解决?shell

第二个问题:服务器CPU占用率高达到100%排查和解决?数据库

第三个问题:有哪些工具可以快速查看线程使用状况?编程

本文对这三个问题进行总结整理,经过实例演示讲解,精彩干货,不容错过啊!服务器

前戏就这么多,高潮会不少,作好了,让咱们直奔主题,发动小船,Let's go!工具

小船

01 Java死锁排查和解决

要排查和解决死锁,首先思考三个问题:

1. 什么是死锁?

2. 为何会出现死锁?

3. 怎么排查代码中出现了死锁?

4. 如何避免写出死锁的代码?

做为技术人员(工程师),在出现问题的时候,可以尽快的去解决这个问题。可是在学习技术知识的时候,仍是脚踏实地,多问一些为何,一个好的问题,可以让本身思考,这方面的能力也必定要锻炼锻炼哦,这样才能更好的理解和掌握知识,并探究/触碰到更深刻的地方。

一、啥是死锁?

死锁是指两个或两个以上的进程在执行过程当中,因为竞争资源或者因为彼此通讯而形成的一种阻塞的现象,若无外力做用,它们都将没法推动下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。[百度百科:死锁]

死锁图示

注:进程和线程均可以发生死锁,只要知足死锁的条件!

二、为啥子会出现死锁?

从上面的概念中咱们知道

(1)必须是两个或者两个以上进程(线程)

(2)必须有竞争资源

三、怎么排查代码中出现了死锁?【重点来了】

首先整一个死锁的代码,看例子:

死锁小demo

上面这段代码执行后,就会出现死锁,那么排查的方法有以下:

第一个姿式:使用 jps + jstack

:在windons命令窗口,使用jps -l【不会使用jps请自行查询资料】

jps -l 命令

:使用 jstack -l 12316 【不会使用jstack请自行查询资料】

jstack

第二个姿式:使用jconsole

在window打开 JConsole,JConsole是一个图形化的监控工具!

:在windons命令窗口 ,输出 JConsole,以下图:

这里写图片描述

:选择到线程的tab上,以下截图。

这里写图片描述

第三个姿式:使用Java Visual VM

在window打开 jvisualvm,jvisualvm是一个图形化的监控工具!

:在windons命令窗口 ,输出 jvisualvm

Java Visual VM

:依然是切换到线程这个TAB上,很明显的就有提示!

死锁检测

四、如何避免死锁?

上面说了死锁出现的缘由以及经过三种方式来检测和排查死锁,下面更重要的东西来了,就是如何避免死锁,若是可以让写出的代码避免死锁出现也就没有上面这些排查的过程了。最好的是从源头控制问题,而不是后期遇到问题在去填坑。

我看了阿里巴巴中最新的开发规约,里面有对避免死锁的说明,具体以下:


【强制】对多个资源、数据库表、对象同时加锁时,须要保持一致的加锁顺序,不然可能会 形成死锁。 说明:线程一须要对表 A、B、C 依次所有加锁后才能够进行更新操做,那么线程二的加锁顺序也必须是 A、B、C,不然可能出现死锁。


0二、Java CPU 100% 排查技巧

第一个姿式,步骤有点多,难度四星

平时多积累一点,这样在遇到问题的时候就少句求人的话。若是在实际的开发中遇到CPU 100%问题,要怎么排查呢?若是你没有遇到过这个问题,请先本身思考10s,若是你遇到过,这个时候也正好能够在回顾一遍。

、 使用top命令查看cpu占用资源较高的PID

top命令

当前占用cup100% 的PID为3455。

、经过jps找到当前用户下的java程序PID

执行jps -l可以打印出全部的应用的PID,找到有一个PID和这个cpu使用100%同样的ID!!!就知道是哪个服务了。知道了对应的服务,在接着后续的分析步骤。

、 使用 pidstat -p < PID > 1 3 -u -t

-p:指定进程号
-u:默认的参数,显示各个进程的cpu使用统计
-t:显示选择任务的线程的统计信息外的额外信息

这里写图片描述这里写图片描述

、找到cpu占用较高的线程TID ,经过上图发现是 3467的TID占用cup较大

、 由于jstack命令输出文件记录的线程ID是16进制。所以咱们先将TID转换为十六进制的表示方式,转换方式能够参考下图。

3467转为十六进制 d8d,注意是小写!! 记录下来,后面会使用。

巧转进制、经过jstack [-l] PID输出当前进程的线程信息

jstack PID  /temp/test.log

、查找 TID对应的线程(输出的线程id为十六进制),找到对应的代码,使用命令查找哦,不要肉眼比对,具体命令请思考,给你表现机会。

查找

找到以后具体分析这个线程在干什么,为何会占用这么多的 CUP资源。

PS:线程的几种状态以下说明:

NEW,未启动的。不会出如今Dump中。
RUNNABLE,在虚拟机内执行的。
BLOCKED,受阻塞并等待监视器锁。
WATING,无限期等待另外一个线程执行特定操做。
TIMED_WATING,有时限的等待另外一个线程的特定操做。
TERMINATED,已退出的。

第二个姿式,待开发[奸笑脸]

此处省略……,好多字。

03 推荐两个高效排查问题工具

 :show-busy-java-threads

在这里插入图片描述

官网地址:show-busy-java-threads: https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#-show-busy-java-threads

简单安装和使用过程:

  1. 下载 show-busy-java-threads
  2. 上传服务器,而后进行解压
  3. 而后执行对应的命令

这里写图片描述

:阿里开源的问题定位神器 arthas 来定位问题。

官网地址:arthas :https://alibaba.github.io/arthas/index.html

这个里面有不少命令,如thread 支持一键展现当前最忙的前N个线程并打印堆栈,最简单的 thread -n 10 便可将最忙碌的十个线程快照打印出来,真正高效。

在这里插入图片描述

定位神器 arthas 安装过程就作介绍了,若是你尚未用过这个工具,我建议必定去用一下,说不定你会爱上它!

04 总结

本文内容比较多,基本上是手把手的教程了,但愿可以对你有所帮助,也建议没有遇到相似问题的伙伴,看完以后必定要亲自去实践一下操做过程,若是没有环境能够自行想办法搞一个测试例子。仍是老话:不要眼高手低,看了和作了本质上两个概念,最终收获的也必定不一样。

05 彩蛋-另外一个姿式

也能够经过使用jstack找到系统的代码性能问题

一、在进行压力测试的时候,使用jps找到应用的PID

二、而后使用jstack输出出压力测试时候应用的dump信息

三、分析输出的日志文件中那个方法block线程占用最多,这里多是性能有问题,找到对应的代码分析


谢谢你的阅读,若是您以为这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到!祝你天天开心愉快!


 

无论作什么,只要坚持下去就会看到不同!在路上,不卑不亢!

 

愿你我在人生的路上能都变成最好的本身,可以成为一个独挡一面的人

© 天天都在变得更好的阿飞云

相关文章
相关标签/搜索