JVisualVM 是 JDK 自带的性能检测工具,路径在 %JAVA_HOME%/bin 下面。双击 jvisualvm.exe 可以打开程序,程序界面如下:

上图中,左边的应用程序“本地”下面有三个 java 进程,分别是 IntelliJ Platform、VisualVM 和 org.jetbrains.jps.cmdline.Launcher。双击 org.jetbrains.jps.cmdline.Launcher java 进程,分析该进程的详细信息,如下图:

上图中,展示了该 java 进程的线程信息。在图片的右下角有五个图例,用来表示线程的状态,本文将逐一介绍这些线程状态。
处于这种状态的线程对于操作系统而言,要么是正在占用CPU时间片运行的线程,要么是已经就绪的线程,只要有CPU时间片分配到,就可以直接运行,对应 Java 中 Runnable 状态。实例:
public class RunningThreadState {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
public void run() {
while(true) {}
}
}, "thread-running");
t.start();
}
}运行效果如下图:

处于睡眠状态的线程,通过调用Thread.sleep()方法让线程进行这种状态,此种状态的线程不占用CPU,但是不释放锁资源。实例:
public class SleepingThreadState {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
}catch (InterruptedException e) {}
}
}
}, "thread-sleeping");
t.start();
}
}运行效果如下图:

通过调用 Object.wait()、Thread.join() 等方法让线程进入这种状态,这种状态的线程不仅会让出 CPU 资源,也会让出所占用的锁资源。实例:
public class WaitThreadState {
public static void main(String[] args) {
final Thread t = new Thread(new Runnable() {
public void run() {
while (true){}
}
});
t.start();
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
// 等待线程 t 终止
t.join();
} catch (InterruptedException e) {}
}
}, "thread-waiting");
t1.start();
}
}运行效果如下图:

通过调用 LockSupport 类中的一些列 park 方法进行此种状态。这种状态是线程没有占用锁,但是可以直接让线程让出 CPU,其他的方法都提到了锁的概念。实例:
public class ParkThreadState {
public static void main(String[] args) {
// LockSupport.park 会让线程进入 park 状态,
// 其实就是不涉及锁的情况下,直接让线程让出 CPU 资源
Thread t = new Thread(new Runnable() {
public void run() {
LockSupport.park();
}
}, "thread-park");
t.start();
}
}运行效果如下图:

通过抢占 synchronized 中的锁而进入的状态。实例:
public class MonitorThreadState {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
say();
}
}, "thread-monitor1");
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
say();
}
}, "thread-monitor2");
t2.start();
}
// 某个线程获得锁后就死循环不释放锁,另一个线程一直等待该锁
private synchronized static void say() {
while(true) {
try {
// 下面两个操作都会让出 CPU,但是不释放锁资源
// 这就导致另一个线程永远也不能获得 say() 方法的锁
System.out.println("synchronized:" + Thread.currentThread());
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500));
Thread.sleep(500);
}catch (Exception e) {}
}
}
}运行效果如下图:
