美文网首页优化及排查
Java死锁排查和Java CPU 100% 排查的步骤整理

Java死锁排查和Java CPU 100% 排查的步骤整理

作者: 阿飞云漫步 | 来源:发表于2018-06-17 23:40 被阅读87次

    工欲善其事,必先利其器

    简介

    本篇整理两个排查问题的简单技巧,一个是java死锁排查,这个一般在面试的时会问到,如果没有写多线程的话,实际中遇到的机会不多;第二个是java cpu 100%排查,这个实际的开发中,线的应用出现这个问题可能性比较大,所以这里简单总结介绍一下,对自己学习知识的一个整理,提高自己的解决问题能力。

    一、Java死锁排查

    通过标题我们就要思考三个问题:

    1. 什么是死锁?
    2. 为什么会出现死锁?
    3. 怎么排查代码中出现了死锁?

    作为技术人员(工程师),在面对问题的时候,可能需要的能力是怎么去解决这个问题。但是在学习技术知识的时候,那就要多问为什么,一定要锻炼自己这方面的能力,这样才能更好的掌握知识。

    解答

    1. 什么是死锁?

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

    死锁图示

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

    1. 为什么会出现死锁?

    从上面的概念中我们知道
    (1)必须是两个或者两个以上进程(线程)
    (2)必须有竞争资源

    1. 怎么排查代码中出现了死锁?【重点来了
      首先写一个死锁的代码,看例子:
    /**
     * 
     * 使用jstack 排查死锁
     * @author dufyun
     *
     */
    public class JStackDemo {
        public static void main(String[] args) {
            Thread t1 = new Thread(new DeadLockTest(true));//建立一个线程
            Thread t2 = new Thread(new DeadLockTest(false));//建立另一个线程
            t1.setName("thread-dufy-1");
            t2.setName("thread-dufy-2");
            t1.start();//启动一个线程
            t2.start();//启动另一个线程
        }
    }
    class DeadLockTest implements Runnable {
        public boolean falg;// 控制线程
        DeadLockTest(boolean falg) {
            this.falg = falg;
        }
        public void run() {
            /**
             * 如果falg的值为true则调用t1线程
             */
            if (falg) {
                while (true) {
                    synchronized (Demo.o1) {
                        System.out.println("o1 " + Thread.currentThread().getName());
                        synchronized (Demo.o2) {
                            System.out.println("o2 " + Thread.currentThread().getName());
                        }
                    }
                }
            }
            /**
             * 如果falg的值为false则调用t2线程
             */
            else {
                while (true) {
                    synchronized (Demo.o2) {
                        System.out.println("o2 " + Thread.currentThread().getName());
                        synchronized (Demo.o1) {
                            System.out.println("o1 " + Thread.currentThread().getName());
                        }
                    }
                }
            }
        }
    }
    
    class Demo {
        static Object o1 = new Object();
        static Object o2 = new Object();
    }
    
    

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

    使用 jps + jstack

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

    jps -l 命令

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


    jstack

    使用jconsole

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

    在windons命令窗口 ,输出 JConsole


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

    使用Java Visual VM

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

    在windons命令窗口 ,输出 jvisualvm

    Java Visual VM 死锁检测

    二、Java CPU 100% 排查

    这个如果在实际的应用开发中遇到,要怎么排查呢?

    这里没有一步步的图示过程,只有一个简单的操作过程!有空写一个详细的例子。

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


    top命令

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

    执行 jps -l 能够打印出所有的应用的PID,找到有一个PID和这个cpu使用100%一样的ID!!就知道是哪一个服务了。

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

    这里写图片描述

    4 、 找到cpu占用较高的线程TID

    通过上图发现是 3467的TID占用cup较大

    5、 将TID转换为十六进制的表示方式

    将3467转为十六进制 d8d,注意是小写!

    巧转进制

    6、 通过jstack -l <PID> 输出当前进程的线程信息

    使用jstack 输出当前PID的线程dunp信息

    7、 查找 TID对应的线程(输出的线程id为十六进制),找到对应的代码

    查找

    三、压力测试使用jstack找到系统的代码性能问题

    1、在进行压力测试的时候,使用jps找到应用的PID
    2、然后使用jstack输出出压力测试时候应用的dump信息
    3、分析输出的日志文件中那个方法block线程占用最多,这里可能是性能有问题,找到对应的代码分析

    参考

    1、Java应用CPU占用100%原因分析
    2、[Java] CPU 100% 原因查找解决
    3、线上应用故障排查系列
    4、分析JAVA应用CPU占用过高的问题


    如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到,谢谢!

    如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
    祝你今天开心愉快!


    欢迎访问我的csdn博客,我们一同成长!

    不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!

    博客首页 : http://blog.csdn.net/u010648555

    相关文章

      网友评论

        本文标题:Java死锁排查和Java CPU 100% 排查的步骤整理

        本文链接:https://www.haomeiwen.com/subject/mhygeftx.html