写一个示例代码,把几种常见的情况都开一个线程运行
package cn.oopeak.juc.juc1;
import cn.hutool.core.thread.ThreadUtil;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author fhf
* @since 2024/7/5
*/
public class VisualVMThreadStatus {
public static void main(String[] args) {
VisualVMThreadStatus visualVMThreadStatus = new VisualVMThreadStatus();
// 创建线程,但是不调用start
visualVMThreadStatus.create();
// 调用sleep方法休眠
visualVMThreadStatus.sleep();
// 调用wait方法
visualVMThreadStatus.callWait();
// 调用wait(timeout)方法
visualVMThreadStatus.callWaitTimeOut();
// 同步代码块里面,一个能拿到锁,一个拿不到阻塞
visualVMThreadStatus.sync();
// juc包中的可重入锁,让线程lock拿不到锁
visualVMThreadStatus.juc();
// 调用LockSupper.park方法
visualVMThreadStatus.lockSupport();
for (; ; ) ;
}
private void create() {
new Thread(() -> {
for (; ; ) ;
}, "1-start");
}
public void sleep() {
new Thread(() -> {
try {
TimeUnit.DAYS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "2-sleep").start();
}
public void callWait() {
new Thread(() -> {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}, "3-wait").start();
}
public void callWaitTimeOut() {
new Thread(() -> {
synchronized (this) {
try {
wait(1000000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}, "4-wait-timeout").start();
}
public void sync() {
Object lock = new Object();
new Thread(() -> {
synchronized (lock) {
for (; ; ) ;
}
}, "5-synchronized持有锁").start();
ThreadUtil.sleep(100);
new Thread(() -> {
synchronized (lock) {
System.out.println("t-synchronized等待锁");
}
}, "6-synchronized等待锁").start();
}
public void juc() {
ReentrantLock r = new ReentrantLock();
// 先占用锁
r.lock();
new Thread(() -> {
// 这里就拿不到了
r.lock();
}, "7-juc-lock").start();
}
public void lockSupport() {
new Thread(() -> {
LockSupport.park();
}, "8-lockSupport").start();
}
}
按照上面的代码运行结果,查看VisualVM里面的线程可以得出以下结论:
- 新建一个线程,但是不调用
start
方法不会显示在列表中; - 正常执行代码的线程,显示的是
Running
(运行)状态; - 调用线程的
sleep
方法,显示的是Sleep
(休眠)状态; - 调用
wait()
方法和调用wait(timeout)
,显示的是Wait
(等待)状态; - 执行
synchronized
代码块(synchronized
方法也一样)如果获取到了锁,显示的是Running
运行状态;如果未获取到锁,显示的是Monitor
(监视)状态。Monitor
状态其实就是阻塞状态; - 调用juc包下的
ReentrantLock
类的lock
方法,未拿到锁的情况下,会显示Park
(驻留)状态; - 调用
LockSupport.park()
方法,会显示Park
(驻留)状态。
我这个VisualVM是官网下载的新版,这个界面和java8自带的差别在于Monitor监视器的颜色,旧版的颜色在一些低质量显示器上还真的和park的颜色分不清
旧的截图:
线程转储中线程的状态