java线程状态与jstack

背景


在实际的项目中,我们在编写一些高并发的项目的时候,经常会自己的来控制线程,但是又很容易出现问题,一旦出现问题又很难debug调试。笔者在实际中会经常起多线程来并发的执行任务,总结了一些排查多线程的问题的方法。

工具使用

如何借助一些工具来排查线程上的bug?

  1. jps: 可以查看当先系统运行了哪些java进程,同时会打印进程号。
C:\Users\robin>jps
8976 DeadLock
10588
4700 Launcher
6492 Jps
  1. jstack: 可以根据进程号来查看该进程里线程的详细状态。
jstack 8976 > d:/DeadLock.txt
  1. top: linux下查看系统资源的指令,我们可以看自己java进程的cpu和内存占用情况。

线程的状态

java 线程的状态:
NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED还有RUNNING、DEADLOCK

先来看下jdk的源码,看下官方对线程的几种状态的阐述:

public enum State {
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,

    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * 
    *
  • {@link Object#wait() Object.wait} with no timeout
  • *
  • {@link #join() Thread.join} with no timeout
  • *
  • {@link LockSupport#park() LockSupport.park}
  • *
* *

A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called Object.wait() * on an object is waiting for another thread to call * Object.notify() or Object.notifyAll() on * that object. A thread that has called Thread.join() * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: *

    *
  • {@link #sleep Thread.sleep}
  • *
  • {@link Object#wait(long) Object.wait} with timeout
  • *
  • {@link #join(long) Thread.join} with timeout
  • *
  • {@link LockSupport#parkNanos LockSupport.parkNanos}
  • *
  • {@link LockSupport#parkUntil LockSupport.parkUntil}
  • *
*/ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }

从以上的注释中我们可以发现:

  1. NEW: 是线程这个对象刚被new出来,还不能被执行。

  2. RUNNABLE: 这个状态是线程已经被new出来了,并且调用了start()方法,此线程随时被执行,只要分配到cpu时间片就能进入执行状态。

  3. BLOCKED: 这个状态是执行的线程遇到遇到同步方法(synchronized)或者同步代码块而没有得到锁,将进入阻塞状态。

  4. WAITING: 当执行的线程调用了join() 或者 wait() 方法的时候,就会进入等待状态,直到被唤醒。

  5. TIMED_WAITING: 这个状态就是当用了sleep(1000)或者join(1000)或者wait(1000)时,执行的线程就会进入等待状态,与WAITING不同的是,这个状态的等待是有时间限制的。

  6. TERMINATED: 这个状态表示线程已经执行完成了。

  7. RUNNING: 执行的中的线程的状态,官网认为正常执行中的线程是属于正常的,也就没有打印出运行中的状态。如果你想看运行中的线程信息,那么可以取看自己项目的日志信息或者控制台。

  8. DEADLOCK: 对于这种状态,是死锁状态,一旦出现这种情况的话,需要立即更改,否则会造成意想不到的后果。

对于死锁状态比较重要,我们一定要会识别,下面笔者写了一个死锁,然后使用jstack打印出的日志:

"VM Periodic Task Thread" os_prio=2 tid=0x000000001993f000 nid=0x1c88 waiting on condition 

JNI global references: 22


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00000000038cae58 (object 0x00000000d609a170, a java.util.ArrayList),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00000000038c99b8 (object 0x00000000d609a188, a java.util.ArrayList),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
    at DeadLock.run(DeadLock.java:37)
    - waiting to lock <0x00000000d609a170> (a java.util.ArrayList)
    - locked <0x00000000d609a188> (a java.util.ArrayList)
    at java.lang.Thread.run(Thread.java:748)
"Thread-0":
    at DeadLock.run(DeadLock.java:37)
    - waiting to lock <0x00000000d609a188> (a java.util.ArrayList)
    - locked <0x00000000d609a170> (a java.util.ArrayList)
    at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

可以看出,jstack的日志信息给出非常明显的提示Found one Java-level deadlock: 提示发现一个死锁,可以根据下面的信息,就能定位在哪个类,哪一行发生了死锁。

你可能感兴趣的:(java线程状态与jstack)