监控 Java 线程时,首先要关注的就是线程的运行状态。

一般来说,Java 线程有 6 种状态:

  1. NEW
  2. RUNNABLE
  3. WAITING & TIMED_WAITING
  4. SLEEP
  5. TERMINATED
  6. BLOCK

下面,用代码示例一下各个状态

1. NEW & TERMINATED

这两个状态比较特殊,分别出现在线程运行之前和线程运行之后

这里所说的运行指调用线程的start()方法。

代码:

虽然没有重写run方法,线程会很快结束。但如果在start()后直接调用getState()的话,仍然会返回RUNNABLE,所以耐心的等上一秒吧。

2. RUNNABLE

我们开线程的目的就是要让它跑起来,所以这个状态可以说是线程的主要状态。

它表示线程正如我们预期的一样正在运行。

代码:

运行时,程序会在标准输出里不断输出 running

下面是用 jvisualvm 监控到的情况:

running

图中的 runnable 线程就是我们在代码中启动的线程。

3. SLEEP

休眠状态下,线程不能被唤醒;必须等到休眠时间结束线程才能回到可执行状态。

让线程进入状态需要调用Thread类的sleep方法。调用时指定好需要休眠的时间,线程就可以美美的睡上一觉了。

代码:

jvisualvm 中的情况:

sleep

注:如果用线程 dump 查看,会发现 sleep 线程标示的是 TIMED_WATING

—更新—
但在 TIMED_WATING 后会显示 (sleeping) 作为与 wait 调用的区分

4.WAITING & TIMED_WAITING

和休眠类似,等待状态下的线程也没有在运行。但是等待下的线程可以随时被唤醒。

WAITINGTIMED_WAITING 都是调用wait方法后的状态。区别在于 WATING 没有指定时间,除非被唤醒,否则会一直等下去。而 TIMED_WAITING 因为指定了时间,即使不被唤醒,也会在指定时间到达之后回到可执行状态。

代码:

jvisualvm 中的情况:

waiting

线程 dump 中的情况:

timed_wating

–更新–
可以看到在 TIMED_WATING 后有显示 (on object monitor)
表示调用的是 wait, 而不是 sleep

5.BLOCK

在线程中,可以使用 sychronized 关键字锁住某些资源,以保证其它线程不能同时访问。如果这时其它线程需要这个资源,就会进入阻塞状态。

如果,两个线程同时需要对方锁住的资源,而这些资源又不能被释放,那就会形成死锁。

这里就用死锁来示例阻塞状态

代码:

jvisualvm 中的情况:

deadBlock

  java
  java, jvisualvm, jvm, 线程