jstack 实验分析

1. Block

模拟代码:

 1 /**
 2  * 线程等待锁的情况
 3  * 使用jstack 查看
 4  *  哪个线程正在等待锁
 5  *  线程正在等待哪个锁
 6  *  等待的锁由哪个线程占有
 7  */
 8 public class BlockDemo {
 9     public static void main(String[] args) throws InterruptedException {
10         new Thread(new Runnable() {
11             @Override
12             public void run() {
13                 try {
14                     System.out.println("thread-0 sleep 1000ms");
15                     Thread.sleep(1000);
16                 } catch (InterruptedException e) {
17                     e.printStackTrace();
18                 }
19                 synchronized ("123"){
20                     System.out.println("thread-0 run...");
21                 }
22             }
23         }).start();
24         
25         // main线程占有锁后睡眠
26         synchronized ("123"){
27             System.out.println("main sleep...");
28             Thread.sleep(50000);
29         }
30         System.out.println("main over");
31     }
32 }

状态查看:

 1 C:Userswqz>jps
 2 11792 BlockDemo
 3 12688 Launcher
 4 9816 Jps
 5 1548
 6 
 7 C:Userswqz>jstack -l 11792
 8 2020-03-21 16:57:57
 9 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode):
10 
11 "Thread-0" #11 prio=5 os_prio=0 tid=0x0000000018bab800 nid=0xbc8 waiting for monitor entry [0x00000000197ae000]
12    java.lang.Thread.State: BLOCKED (on object monitor)
13         at cn.wqz.jvm.stack.BlockDemo$1.run(BlockDemo.java:22)
14         - waiting to lock <0x00000000d5ecbb20> (a java.lang.String)
15         at java.lang.Thread.run(Thread.java:748)
16 
17    Locked ownable synchronizers:
18         - None
19 
20  ... 
21 "main" #1 prio=5 os_prio=0 tid=0x0000000002b02800 nid=0x4018 waiting on condition [0x000000000256f000] 22 java.lang.Thread.State: TIMED_WAITING (sleeping) 23 at java.lang.Thread.sleep(Native Method) 24 at cn.wqz.jvm.stack.BlockDemo.main(BlockDemo.java:30) 25 - locked <0x00000000d5ecbb20> (a java.lang.String) 26 27 Locked ownable synchronizers: 28 - None

2. in object.wait()

模拟代码:

 1 /**
 2  * 线程wait情况
 3  */
 4 public class ObjectWaitDemo {
 5     public static void main(String[] args) throws InterruptedException {
 6         new Thread(new Runnable() {
 7             @Override
 8             public void run() {
 9                 System.out.println("thread-0 sleep...");
10                 try {
11                     Thread.sleep(10000);
12                 } catch (InterruptedException e) {
13                     e.printStackTrace();
14                 }
15                 synchronized ("123"){
16                     System.out.println("thread-0 run");
17                     try {
18                         Thread.sleep(5000);
19                     } catch (InterruptedException e) {
20                         e.printStackTrace();
21                     }
22                     System.out.println("thread-0 notify");
23                     "123".notify();
24                 }
25             }
26         }).start();
27 
28         synchronized ("123"){
29             System.out.println("main before wait");
30             "123".wait(); // 不唤则不醒
31             System.out.println("main after wait");
32         }
33     }
34 }

状态查看:

 1 C:Userswqz>jstack -l 2620
 2 2020-03-21 17:11:23
 3 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode):
 4 
 5 "Thread-0" #11 prio=5 os_prio=0 tid=0x0000000018b29000 nid=0x426c waiting on condition [0x000000001973f000]
 6    java.lang.Thread.State: TIMED_WAITING (sleeping)
 7         at java.lang.Thread.sleep(Native Method)
 8         at cn.wqz.jvm.stack.ObjectWaitDemo$1.run(ObjectWaitDemo.java:20)
 9         - locked <0x00000000d5ecc238> (a java.lang.String)
10         at java.lang.Thread.run(Thread.java:748)
11 
12    Locked ownable synchronizers:
13         - None
14 
15 .  .  .
16 
17 "main" #1 prio=5 os_prio=0 tid=0x0000000002a92800 nid=0x3c28 in Object.wait() [0x0000000000c6f000]
18    java.lang.Thread.State: WAITING (on object monitor)
19         at java.lang.Object.wait(Native Method)
20         - waiting on <0x00000000d5ecc238> (a java.lang.String)
21         at java.lang.Object.wait(Object.java:502)
22         at cn.wqz.jvm.stack.ObjectWaitDemo.main(ObjectWaitDemo.java:31)
23         - locked <0x00000000d5ecc238> (a java.lang.String)
24 
25    Locked ownable synchronizers:
26         - None

注意: wait中的线程,不被唤醒的话不会醒来

3. waiting on condition

模拟代码:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * 创建阻塞条件
 * waiting on condition
 */
public class WaitingOnConditionDemo {

    public static void main(String[] args) {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(1);
        blockingQueue.add("123");
        try {
            //阻塞的添加
            blockingQueue.put("123");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

状态查看:

 1 "main" #1 prio=5 os_prio=0 tid=0x0000000002c82800 nid=0x40f8 waiting on condition [0x000000000279f000]
 2    java.lang.Thread.State: WAITING (parking)
 3         at sun.misc.Unsafe.park(Native Method)
 4         - parking to wait for  <0x00000000d6021678> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
 5         at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
 6         at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
 7         at java.util.concurrent.ArrayBlockingQueue.put(ArrayBlockingQueue.java:353)
 8         at cn.wqz.jvm.stack.WaitingOnConditionDemo.main(WaitingOnConditionDemo.java:13)
 9 
10    Locked ownable synchronizers:
11         - None

4. 总结

状态说明:

  • New: 当线程对象创建时存在的状态,此时线程不可能执行;
  • Runnable:当调用thread.start()后,线程变成为Runnable状态。只要得到CPU,就可以执行;
  • Running:线程正在执行;
  • Waiting:执行thread.join()或在锁对象调用obj.wait()等情况就会进该状态,表明线程正处于等待某个资源或条件发生来唤醒自己;
  • Timed_Waiting:执行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就会进该状态,与Waiting的区别在于Timed_Waiting的等待有时间限制;
  • Blocked:如果进入同步方法或同步代码块,没有获取到锁,则会进入该状态;
  • Dead:线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,表示该线程结束
  • 其次,对于jstack日志,我们要着重关注如下关键信息
  • Deadlock:表示有死锁
  • Waiting on condition等待某个资源或条件发生来唤醒自己。具体需要结合jstacktrace来分析,比如线程正在sleep,网络读写繁忙而等待
  • Blocked:阻塞
  • Waiting on monitor entry:在等待获取锁
  • in Object.wait():获取锁后又执行obj.wait()放弃锁
  • 对于Waiting on monitor entry 和 in Object.wait()的详细描述:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。从下图中可以看出,每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 "Active Thread",而其它线程都是 "Waiting Thread",分别在两个队列 " Entry Set"和 "Wait Set"里面等候。在 "Entry Set"中等待的线程状态是 "Waiting for monitor entry",而在 "Wait Set"中等待的线程状态是 "in Object.wait()"

经验:

如果说系统慢,那么要特别关注Blocked,Waiting on condition
如果说系统的cpu耗的高,那么肯定是线程执行有死循环,那么此时要关注下Runable状态。

本文结束。

原文地址:https://www.cnblogs.com/yelao/p/12542310.html