并发编程(三)java线程状态log日志解读 - Stack log 解读

们可能在平时会用到jstack命令,进行线程状态查看,下面简单解读一下jstack中日志。

1示例代码

示例代码如下:

public class ReadStackLog {
    public static void main(String[] args) throws JsonProcessingException {
        new Thread(new TimeWaiting (), "TimeWaitingThread").start();
        new Thread(new Waiting(), "WaitingThread").start();
        // 使用两个Blocked线程,一个获取锁成功,另一个被阻塞
        new Thread(new Blocked(), "BlockedThread-1").start();
        new Thread(new Blocked(), "BlockedThread-2").start();
    }
}
// 该线程不断地进行睡眠
 class TimeWaiting implements Runnable {
    @SneakyThrows
    @Override
    public void run() {
        while (true) {
            Thread.sleep(1000000);
        }
    }
}
// 该线程在Waiting.class实例上等待
 class Waiting implements Runnable {
    @Override
    public void run() {
        while (true) {
            synchronized (Waiting.class) {
                try {
                    Waiting.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
// 该线程在Blocked.class实例上加锁后,不会释放该锁
 class Blocked implements Runnable {
    @SneakyThrows
    public void run() {
        synchronized (Blocked.class) {
            while (true) {
                Thread.sleep(1000000);
            }
        }
    }
}
复制代码

2运行日志查看

我们把程序运行起来,因为线程使用了sleep方法进行休眠,此时程序一直处于正在运行状态:

 

此时打开idea的Terminal面板,进行命令的输入,先输入jps查看线程的pid,再根据就stack pid查看到线程当前类所有栈信息的运行日志。

 

3逐个线程分析

我们摘取有用部分进行查看:

3.1 BlockedThread-2

"BlockedThread-2" #23 prio=5 os_prio=0 tid=0x0000000018f75800 nid=0xe9f0 waiting for monitor entry [0x000000001a67f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.juc.Blocked.run(ReadStackLog.java:45)
        - waiting to lock <0x000000076bb165c0> (a java.lang.Class for com.juc.Blocked)
        at java.lang.Thread.run(Thread.java:748)
复制代码

我们会发现BlockedThread-2这个线程状态是BLOCKED,并且下面提示正在等待Class类型的 Blocked.class锁释放(根据- waiting to lock提示信息得知),并且如果永远不释放,会造成一种死锁。

3.2 BlockedThread-1

"BlockedThread-1" #22 prio=5 os_prio=0 tid=0x0000000018f73800 nid=0xd59c waiting on condition [0x000000001a57e000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.juc.Blocked.run(ReadStackLog.java:45)
        - locked <0x000000076bb165c0> (a java.lang.Class for com.juc.Blocked)
        at java.lang.Thread.run(Thread.java:748)
复制代码

我们会发现BlockedThread-1这个线程状态是TIMED_WAITING,并且下面提示使用了Class类型的 Blocked.class锁(根据- lockerd提示信息得知),只不过目前进入了sleep方法,使线程休眠了。

3.3 WaitingThread

"WaitingThread" #21 prio=5 os_prio=0 tid=0x0000000018f71000 nid=0x6624 in Object.wait() [0x000000001a47f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076bb144a8> (a java.lang.Class for com.juc.Waiting)
        at java.lang.Object.wait(Object.java:502)
        at com.juc.Waiting.run(ReadStackLog.java:31)
        - locked <0x000000076bb144a8> (a java.lang.Class for com.juc.Waiting)
        at java.lang.Thread.run(Thread.java:748)
复制代码

同理我们得知,目前线程状态是WAITING状态,并且显示线程 in Object.wait() ,得知此线程调用了wait()方法,如果不唤醒,则永远等待。

3.4 TimeWaitingThread

"TimeWaitingThread" #20 prio=5 os_prio=0 tid=0x0000000018f6f000 nid=0xe8d0 waiting on condition [0x000000001a37f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.juc.TimeWaiting.run(ReadStackLog.java:20)
        at java.lang.Thread.run(Thread.java:748)
复制代码

可以看出此线程状态是TIMED_WAITING,并且括号里显示了sleeping,说明此线程正在睡眠,等睡眠完成后,就会继续执行,并且此线程还没有任何锁信息。

3.5 其他线程

这里说明一下Finalizer线程

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000155c7800 nid=0xe14c in Object.wait() [0x000000001897e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b588ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x000000076b588ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
复制代码
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001709d000 nid=0xdfc8 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

复制代码

只有进行垃圾收集的时候,才会被notify。 用到我们的 signal Dispatcher。

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000155bf800 nid=0xb88c in Object.wait() [0x000000001887e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b586bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x000000076b586bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
复制代码

Reference Handler线程首先没有垃圾收集,不需要使用强弱引用。其次这个作为引用处理线程,目前我们的线程已经全部完成引用处理,此线程进入WAITING状态,除非加载新的类或者新的引用才会再次生效!

其他线程类似Monitor Ctrl-Break同理可得,不再赘述。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值