在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鎖相關的三個線程,可以看到無論是通過condition的await方法,還是在阻塞等待鎖的過程中,都是處於駐留狀態,而不是我一開始預想的等待狀態,通過查看源碼后發現它們最終都調用了Unsafe的park方法,后續的線程dump也能驗證這一點。
-
pool- 1-threadpool-1就是那個線程池,因為里面的線程處於空閑狀態,也屬於駐留。
線程dump

