jvisualvm 工具中线程各种状态的含义

JVisualVM 是 JDK 自带的性能检测工具,路径在 %JAVA_HOME%/bin 下面。

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

jvisualvm 工具中线程各种状态的含义

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

jvisualvm 工具中线程各种状态的含义

上图中,展示了该 java 进程的线程信息。在图片的右下角有五个图例,用来表示线程的状态,本文将逐一介绍这些线程状态。

运行(Running)

处于这种状态的线程对于操作系统而言,要么是正在占用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();
    }

}

运行效果如下图:

jvisualvm 工具中线程各种状态的含义

休眠(Sleeping)

处于睡眠状态的线程,通过调用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();
    }

}

运行效果如下图:

jvisualvm 工具中线程各种状态的含义

等待(Wait)

通过调用 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();
    }

}

运行效果如下图:

jvisualvm 工具中线程各种状态的含义

驻留(Park)

通过调用 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();
    }

}

运行效果如下图:

jvisualvm 工具中线程各种状态的含义

监视(Monitor)

通过抢占 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) {}
        }
    }

}

运行效果如下图:

jvisualvm 工具中线程各种状态的含义

在年轻人的颈项上,没有什么东西能比事业心这颗灿烂的宝珠更迷人的了。 —— 哈菲兹
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号