• JDK常用命令(二)jstack


    Dump

      Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中。Dump文件一般用来给驱动程序编写人员调试驱动程序用的,在java中用来分析正在运行的程序在内存中的堆栈信息。

    jstack

      Jstack是Jdk自带的线程(栈)跟踪工具,主要用来查看Java线程的调用堆栈,可以用来分析线程问题(如死锁)。可根据指定java进程ID打印指定Java进程的线程堆栈信息。可以定位到线程阻塞、死循环、死锁等源头代码,java程序员必会技能之一。

      用法很简单:jstack pid,一般不加参数直接用就行

    Options:
      -F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
      -m to print both java and native frames (mixed mode)
      -l long listing. Prints additional information about locks
      -h or -help to print this help message

      jstack可以针对活着的进程做本地的或远程的线程dump或针对core文件做线程dump。jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

    java线程状态

      1.NEW,未启动的。不会出现在Dump中。
      2.RUNNABLE,在虚拟机内执行的。运行中状态,可能里面还能看到locked字样,表明它获得了某把锁。
      3.BLOCKED,受阻塞并等待监视器锁。被某个锁(synchronizers)給block住了。
      4.WATING,无限期等待另一个线程执行特定操作。等待某个condition或monitor发生,一般停留在park(), wait(), sleep(),join() 等语句里。
      5.TIMED_WATING,有时限的等待另一个线程的特定操作。和WAITING的区别是wait() 等语句加上了时间限制 wait(timeout)。
      6.TERMINATED,已退出的。

    Monitor

      在多线程的 JAVA程序中,实现线程之间的同步,就是通过Monitor实现的。 Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。

      进入区(Entrt Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。

      拥有者(The Owner):表示某一线程成功竞争到对象锁。

      等待区(Wait Set):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。

      从图中可以看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在“Wait Set”中等待的线程状态是 “in Object.wait()”。 先看 “Entry Set”里面的线程。我们称被 synchronized保护起来的代码段为临界区。当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。对应的 code就像:

    1 synchronized(obj) {
    2     //...
    3 }

    多线程分析

    线程1获取到锁,处于RUNNABLE状态,线程2处于BLOCK状态

    thread-1:locked <0x000000076bf62208>说明线程1对地址为0x000000076bf62208对象进行了加锁;

    thread-2:waiting to lock <0x000000076bf62208> 说明线程2在等待地址为0x000000076bf62208对象上的锁;

    thread-2:waiting for monitor entry [0x000000001e21f000]说明线程2是通过synchronized关键字进入了监视器的临界区,并处于"Entry Set"队列,等待monitor

    线程1和2都处于WAITING状态

      线程1和2都是先locked <0x000000076bf62500>,再waiting on <0x000000076bf62500>,之所以先锁再等同一个对象,是因为wait方法需要先通过synchronized获得该地址对象的monitor;

      waiting on <0x000000076bf62500>说明线程执行了wait方法之后,释放了monitor,进入到"Wait Set"队列,等待其它线程执行地址为0x000000076bf62500对象的notify方法,并唤醒自己

    死循环

    1 package io.guangsoft.jstack;
    2 
    3 public class EndlessLoop {
    4     public static void main(String args[]) {
    5         while(true) {
    6             System.out.println("endless loop...");
    7         }
    8     }
    9 }

    使用jstack查看堆栈信息

    我们可以清晰的看到main线程处于RUNNABLE,并能看到是哪个包哪个类下的第几行。

    线程等待

     1 package io.guangsoft.jstack;
     2 
     3 import java.util.concurrent.ExecutorService;
     4 import java.util.concurrent.Executors;
     5 
     6 class TestTask implements Runnable {
     7     @Override
     8     public void run() {
     9         synchronized (this) {
    10             try {
    11                 wait();
    12             } catch (InterruptedException e) {
    13                 e.printStackTrace();
    14             }
    15         }
    16     }
    17 }
    18 
    19 public class Wait{
    20     public static void main(String[] args) throws Exception {
    21         ExecutorService ex = Executors.newFixedThreadPool(1);
    22         ex.execute(new TestTask());
    23     }
    24 }

    死锁

     1 package io.guangsoft.jstack;
     2 
     3 import java.util.concurrent.ExecutorService;
     4 import java.util.concurrent.Executors;
     5 
     6 class Task implements Runnable {
     7     private int order;
     8     private Object obj1;
     9     private Object obj2;
    10 
    11     public Task(int order, Object obj1, Object obj2) {
    12         this.order = order;
    13         this.obj1 = obj1;
    14         this.obj2 = obj2;
    15     }
    16 
    17     public void test1() throws InterruptedException {
    18         synchronized (obj1) {
    19             //建议线程调取器切换到其它线程运行
    20             Thread.yield();
    21             synchronized (obj2) {
    22                 System.out.println("test1");
    23             }
    24 
    25         }
    26     }
    27     public void test2() throws InterruptedException {
    28         synchronized (obj2) {
    29             Thread.yield();
    30             synchronized (obj1) {
    31                 System.out.println("test2");
    32             }
    33 
    34         }
    35     }
    36 
    37     @Override
    38     public void run() {
    39         while (true) {
    40             try {
    41                 if(this.order == 1){
    42                     this.test1();
    43                 } else {
    44                     this.test2();
    45                 }
    46             } catch (InterruptedException e) {
    47                 e.printStackTrace();
    48             }
    49         }
    50     }
    51 }
    52 
    53 public class DeadLock {
    54     public static void main(String[] args) throws Exception {
    55         Object obj1 = new Object();
    56         Object obj2 = new Object();
    57         ExecutorService ex = Executors.newFixedThreadPool(10);
    58         for (int i = 0; i < 10; i++) {
    59             int order = i % 2 == 0 ? 1 : 0;
    60             ex.execute(new Task(order, obj1, obj2));
    61         }
    62     }
    63 }

  • 相关阅读:
    【LeetCode】Validate Binary Search Tree
    【LeetCode】Search in Rotated Sorted Array II(转)
    【LeetCode】Search in Rotated Sorted Array
    【LeetCode】Set Matrix Zeroes
    【LeetCode】Sqrt(x) (转载)
    【LeetCode】Integer to Roman
    贪心算法
    【LeetCode】Best Time to Buy and Sell Stock III
    【LeetCode】Best Time to Buy and Sell Stock II
    CentOS 6 上安装 pip、setuptools
  • 原文地址:https://www.cnblogs.com/guanghe/p/10531872.html
Copyright © 2020-2023  润新知