VisualVM是壓測過程中經常用到的一個工具,但是在分析過程中對其中的幾種狀態瞭解的不太清楚,通過查閱資源和代碼中測試,基本搞懂了這些狀態的區別。
狀態說明:
-
Running
處於這種狀態的線程對於操作系統而言,要麼是正在佔用CPU時間片運行的線程,要麼是已經就緒的線程,只要有CPU時間片分配到,就可以直接運行,對應Java中Runnable狀態。 -
Sleeping
處於睡眠狀態的線程,通過調用Thread.sleep()方法讓線程進行這種狀態,此種狀態的線程不佔用CPU,但是不釋放鎖資源。 -
Wait
通過調用Object.wait()、Thread.join()等方法讓線程進入這種狀態,這種狀態的線程不僅會讓出CPU資源,也會讓出所佔用的鎖資源。 -
Park
通過調用LockSupport類中的一些列park方法進行此種狀態。這種狀態是線程沒有佔用鎖,但是可以直接讓線程讓出CPU,其他的方法都提到了鎖的概念。 -
Monitor
通過搶佔synchronized中的鎖而進入的狀態。
其實還有一些間接調用上述方法的鎖,也會進行提到的某種狀態,具體情況看看源碼分析下吧。
廢話少說,看看我的代碼如果先線程進入不同的狀態吧。
模擬代碼如下:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
*
* visualvm中線程幾種狀態的模擬
* 主要涉及到
* Running: 運行態,此時正在使用CPU的時間片
* Sleeping:休眠狀態,調用Thread.sleep(),不佔用CPU
* Wait:調用Object.wait、Thread.join等方法會進入這個狀態
* Park:調用LockSupport.park等方法會進入這個狀態,底層調用的是
* Monitor:通過synchronized搶佔鎖
**/
public class ThreadStateSimulateTest {
public static void main(String[] args) {
// 模擬sleeping, Thread.sleep()會使線程進入Sleeping狀態
Thread t = new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
}catch (InterruptedException e) {}
}
}, "simulateSleeping");
t.start();
// 調用Thread.join的線程會進入Wait狀態
Thread t1 = new Thread(() -> {
System.out.println("開始模擬wating");
try {
t.join();
}catch (InterruptedException e) {}
}, "simulateWaiting");
t1.start();
// LockSupport.park會讓線程進入park狀態(其實就是不涉及鎖的情況下,直接讓線程讓出cpu)
Thread t2 = new Thread(() -> {
System.out.println("park方法直接讓線程讓出cpu");
LockSupport.park();
}, "simulateParking");
t2.start();
Thread t3 = new Thread(() -> {
say();
}, "simulateMonitor1");
Thread t4 = new Thread(() -> {
say();
}, "simulateMonitor2");
t3.start();
t4.start();
Thread t5 = new Thread(() -> {
while(true) {}
}, "simulateRunning");
t5.start();
}
public synchronized static void say() {
while(true) {
try {
// 下面兩個操作都不會讓出synchronized佔用的鎖資源
System.out.println("synchronized:" + Thread.currentThread());
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500));
Thread.sleep(500);
}catch (Exception e) {}
}
}
}
simulateSleeping線程調用了Thread.sleep(1000);這個方法,直接進入了Sleeping狀態。
simulateWaiting線程調用了t.join();這個方法進入了Wating狀態。
simulateParking調用了LockSupport.park();這個方法進入了Park狀態。
simulateRunning直接就是Running狀態的線程。
simulateMonitor1和simulateMonitor2線程配合使用,會導致先搶到鎖的進入一個循環,不釋放鎖,後來的一個線程只能阻塞等待,進入Monitor狀態。