在使用多线程时,如果使用不当,就会产生一些问题,比如:

线程死锁的条件_线程死锁_线程死锁是什么

先创建一个应用,模拟一个死锁问题和cpu占用率过高的问题,核心代码如下:

/**
 * 模拟一个死锁问题和cpu占用率过高的问题
 */
@RestController
public class ThreadController
{
    @GetMapping("/loop")
    public String dumpWhile()
    {
        new Thread(new WhileThread()).start();
        return "OK";
    }
    @GetMapping("/dead")
    public String dumpDeadlock()
    {
        Thread a = new ThreadRunA();
        Thread b = new ThreadRunB();
        a.start();
        b.start();
        return "OK";
    }
}
class WhileThread implements Runnable{
    @Override
    public void run()
    {
        while (true)
        {
            System.out.println("Thread");
        }
    }
}
class ThreadRunA extends Thread{
    @Override
    public void run()
    {
        System.out.println("======================A====================");
        synchronized (A.A){
            System.out.println("我要开始执行任务A..."+Thread.currentThread().getName());
            try
            {
                Thread.sleep(5000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            synchronized (B.B)
            {
            }
            System.out.println("我在执行任务结束了A..."+Thread.currentThread().getName()+":"+B.B.hashCode()+":"+A.A.hashCode());
        }
    }
}
class ThreadRunB extends Thread{
    @Override
    public void run()
    {
        System.out.println("======================B====================");
        synchronized (B.B){
            System.out.println("我要开始执行任务B..."+Thread.currentThread().getName());
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            synchronized (A.A)
            {
            }
            System.out.println("我在执行任务结束了B..."+Thread.currentThread().getName()+":"+B.B+":"+A.A);
        }
    }
}

死锁导致请求无法响应

将上面的这段运行程序,使用如下命令制造死锁现场:

curl :8080/dead

对于死锁问题的排查,具体操作步骤如下:

第一步,通过 jps 命令,查看Java进程的pid.

第二步,通过 命令查看线程dump日志.

线程死锁的条件_线程死锁是什么_线程死锁

当发现死锁时,可以在打印的dump日志中找到Found one Java-level : 信息,根据信息内容分析问题出现的原因.

线程死锁是什么_线程死锁的条件_线程死锁

是Java虚拟机自带的一种堆栈跟踪工具,它主要用于打印指定Java进行ID中当前时刻的线程dump日志,线程快照是当前Java虚拟机内每一条线程正在执行的方法堆栈的集合. 生成线程快照的主要目的是定位线程出现长时间停顿的原因, 如线程间死锁,死循环,请求外部的资源导致的长时间等待等,语法格式如下:

线程死锁_线程死锁是什么_线程死锁的条件

CPU占用率过高,响应很慢

为了演示CPU过高的场景,先执行如下的命令, 这个命令会让线程进入死循环状态.

curl :8080/loop

上述命令运行完之后,通过top -c 命令可以动态显示进程及其占用资源的排行榜,从结果可以找到占用CPU最高的进程PID.

线程死锁_线程死锁是什么_线程死锁的条件

可以看到,CPU占用率比较高 的PID是21602,定位到该进程之后,我们再从线程的dump日志中去定位.

线程死锁_线程死锁是什么_线程死锁的条件

21602 | grep -A 20 // pid(进程id) | grep 16进制线程 -A 行数

-A 表示显示匹配行及其后面的n行.

通过上述操作后,得到的线程dump信息如下,从该信息中我们发现,在.run()方法中因为某个操作导致cpu占用率高,于是基于这个信息我们可以进行分析从而解决该问题.

线程死锁的条件_线程死锁是什么_线程死锁

上述代码内容其实可以分为三个部分.

。 -2 表示线程名字,为了更好地辨别,建议大家在使用线程的时候自己进行命令.

。 #29,线程的编号。

。 ,表示守护线程。

。 prio,线程的优先级,Java 中的线程优先级分为 1~10 个级别,数字越高表示优先级高,优先级高的线程能够有更高的概率优先得 到 CPU 的执行。

。 ,表示操作系统层面的线程优先级,Java 中配置的线程优先级最终会映射到操系统中的线程优先级。

。 tid=,JM 内部线程 ID

。 nid,系统线程ID

。 ,线程状态

线程死锁_线程死锁是什么_线程死锁的条件

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,永久会员只需109元,全站资源免费下载 点击查看详情
站 长 微 信: nanadh666

声明:1、本内容转载于网络,版权归原作者所有!2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!