在java自带的工具JVirtualVM中线程有以下几种状态:

先说结论,各状态含义如下,后面有详细的demo测试验证:
运行(runnable):正在运行中的线程。
休眠(timed_waiting):休眠线程,例如调用Thread.sleep方法。
等待(waiting):等待唤醒的线程,可通过调用Object.wait方法获得这种状态,底层实现是基于对象头中的monitor对象。
驻留(waiting):等待唤醒的线程,和等待状态类似,只不过底层的实现方式不同,处于这种状态的例子有线程池中的空闲线程,等待获取reentrantLock锁的线程,调用了reentrantLock的condition的await方法的线程等等,底层实现是基于Unsafe类的park方法,在AQS中有大量的应用。
监视(blocked):等待获取monitor锁的线程,例如等待进入synchronize代码块的线程。
- private static final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); private static final ReentrantLock reentrantLockTest = new ReentrantLock(); public static void main(String[] args) { //基于println方法中的synchronize代码块测试运行或者监视线程
- Thread thread1 = new Thread(() -> { while (true) {
- System.out.println("运行或者监视线程1");
- }
- }, "运行或者监视线程1");
- thread1.start(); //基于println方法中的synchronize代码块测试运行或者监视线程
- Thread thread2 = new Thread(() -> { while (true) {
- System.out.println("运行或者监视线程2");
- }
- }, "运行或者监视线程2");
- thread2.start(); //monitor对象等待线程
- Object lock = new Object(); Thread thread3 = new Thread(() -> { synchronized (lock) { try {
- lock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "等待线程synchronized");
- thread3.start(); //reentrantLock中的条件对象调用await方法线程为驻留线程
- ReentrantLock reentrantLock = new ReentrantLock(); Condition condition = reentrantLock.newCondition(); Thread thread4 = new Thread(() -> {
- reentrantLock.lock(); try {
- condition.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- reentrantLock.unlock();
- }
- }, "等待线程reentrantLock");
- thread4.start(); //休眠线程
- Thread thread5 = new Thread(() -> { try {
- Thread.sleep(1000000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }, "休眠线程");
- thread5.start(); Thread thread6 = new Thread(ThreadTest::lockMethod, "reentrantLock运行线程");
- thread6.start(); //等待获取reentrantLock的线程为驻留线程
- Thread thread7 = new Thread(() -> { try {
- TimeUnit.MICROSECONDS.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- lockMethod();
- }, "reentrantLock监视线程");
- thread7.start(); //线程池中的空闲线程为驻留线程
- singleThreadExecutor.execute(() -> { //线程池中的线程是懒加载,需要运行任务之后才会产生线程
- System.out.println("驻留线程运行");
- });
- } private static void lockMethod() {
- reentrantLockTest.lock(); try { while (true) {
- }
- } finally {
- reentrantLockTest.unlock();
- }
- } //println源码也简单贴一下
- //java.io.PrintStream#println(java.lang.String)
- public void println(String x) { //this表示System.out这个PrintStream对象
- synchronized (this) {
- print(x);
- newLine();
- }
- }
以上代码运行之后,打开JVirtualVM查看线程如下:

根据代码的顺序从上至下讲:
两个运行或者监视线程的System.out.println()语句因为抢同一个synchronize锁,可以很明显的看出是在交替运行,状态分别处于运行和监视状态。
等待线程synchronize因为调用了Object的wait方法,一直处于等待状态。
休眠线程省略。
重点是和reentrantLock锁相关的三个线程,注意下上图中有一个地方写错了,等待线程reentrantLock,实际应该是驻留线程reentrantLock,可以看到无论是通过condition的await方法,还是在阻塞等待锁的过程中,都是处于驻留状态,而不是我一开始预想的等待状态,通过查看源码后发现它们最终都调用了Unsafe的park方法,后续的线程dump也能验证这一点。
pool- 1-threadpool-1就是那个线程池,因为里面的线程处于空闲状态,也属于驻留。
