• 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状态。

    本文结束。

  • 相关阅读:
    (转)MySQL中MyISAM引擎与InnoDB引擎性能简单测试
    (转)数据库水平切分的实现原理解析
    ECShop笔记(品牌类)
    ECShop笔记(通用类)
    (转)InnoDB的性能(zz)
    ECSHOP笔记(商品类 三)
    ECShop笔记(积分类)
    ECShop笔记(商品类)
    ECShop笔记(二)
    phpcms 点击排行榜的改进
  • 原文地址:https://www.cnblogs.com/yelao/p/12542310.html
Copyright © 2020-2023  润新知