Java分析线程信息-入门版

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


jps+stack

jps:jdk提供的一个查看当前java进程命令

参数含义
jps端口号+进程名
jps -l端口号+应用程序main class的完整package名 or 应用程序的jar文件完整路径名
jps -vjvm参数

jstack:查看jvm栈信息

jstack -l pid

tid指Java Thread id。nid指native线程的id。prio是线程优先级。
在这里插入图片描述
注意1:线程当前所处的一个状态 and 线程栈的起始地址

  • waiting on condition:线程等待一个条件,此时该线程仍然占有Monitor。
  • waiting for monitor entry:线程在EntrySet中等待,获取Monitor。说明此线程通过 synchronized(obj) {……} 申请进入了临界区,从而进入了下图1中的“Entry Set”队列,但该 obj 对应的 monitor 被其他线程拥有,所以本线程在 Entry Set 队列中等待。
  • in Object.wait():当线程获得了 Monitor,进入了临界区之后,如果发现线程继续运行的条件没有满足,它则调用对象(一般就是被 synchronized 的对象)的 wait() 方法,放弃了 Monitor,进入 “Wait Set”队列。只有当别的线程在该对象上调用了 notify() 或者 notifyAll() ,“ Wait Set”队列中线程才得到机会去竞争进入EntrySet
  • runnable

注意2:线程自身的状态

  • TIMED_WAITING (sleeping):指等待状态,但这里指定了时间,到达指定的时间后自动退出等待状态。sleep指线程处于睡眠状态。
  • WAITING (on object monitor):等待状态,此时线程在WaitSet中
  • RUNNABLE:运行状态
  • BLOCKED (on object monitor):阻塞状态,此时线程在EntrySet中

注意3:线程执行过程中的堆栈信息
注意4:

Monitor对象内部,结合synchrnized关键字进行分析
在这里插入图片描述
同一时刻,只有一个线程成功占有Monitor(获取锁)

  • EntrySet:是线程1进入synchronized临界区,但是monitor此时被别的线程占有,线程1阻塞,进入EntrySet等待竞争Monitor。【线程阻塞】
  • WaitSet,线程1占有Monitor时,发现需要的资源无法获取,此时调用wait,进入WaitSet,等待被notify【线程等待】

实例分析

实例1:sleep

public class Test {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                ok();
            }
        },"t1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                ok();
            }
        },"t2").start();
    }

    public synchronized static void ok(){
        try {
            Thread.sleep(200000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
t1

locked <0x000000076acae290>:由于ok()被synchronized修饰,作为临界区,执行ok()之前,先要给临界区地址上锁
TIMED_WAITING (sleeping):t1执行了sleep(),交出CPU处于等待状态,等到时间到了之后,重新参与CPU竞争。sleep()过程中t1并不会释放锁。
waiting on condition:等待条件是时间

t2

waiting to lock <0x000000076acae290>:执行ok()之前,先要给临界区地址上锁,由于t1已经进行lock。此时t2处于waiting to lock 等待去加锁
BLOCKED (on object monitor):获取锁失败,阻塞
waiting for monitor entry:进入EntrySet中

实例2:死锁

public class Test {
    public static void main(String[] args) {
        Object o1 = new Object();
        Object o2 = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    synchronized (o1){
                        System.out.println("t1 获取o1资源 开始执行");
                        Thread.sleep(2000);
                        synchronized (o2){
                            System.out.println("t1 获取o2资源 开始执行");
                            Thread.sleep(2000);
                            System.out.println("t1 释放o2资源 执行完毕");
                        }
                        System.out.println("t1 释放o1资源 执行完毕");
                    }
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (o2) {
                        System.out.println("t2 获取o2资源 开始执行");
                        Thread.sleep(2000);
                        synchronized (o1) {
                            System.out.println("t2 获取o1资源 开始执行");
                            Thread.sleep(2000);
                            System.out.println("t2 释放o1资源 执行完毕");
                        }
                        System.out.println("t2 释放o2资源 执行完毕");
                    }
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t2").start();
    }
}

在这里插入图片描述
t1、t2在对不同地址lock之后,又想对对方已经锁住的地址进行加锁,造成死锁。
此时都处于阻塞状态BOLCKED
在这里插入图片描述
实例3:wait

public class Test {
    public static Object object = new Object();
    public static void main(String[] args) {
       new Thread(new Runnable() {
           @Override
           public void run() {
               ok();
           }
       },"t1").start();
    }

    public static void ok(){
        synchronized (object){
            try {
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述
线程的执行中,先用 synchronized 获得了这个对象的 Monitor(对应于 locked <0x000000076acb1060> );当执行到 object.wait();,线程就放弃了 Monitor 的所有权,进入“Wait Set”队列(对应于 waiting on <0x000000076acb1060> )

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值