美文网首页
JVirtualVM 中线程有以下几种状态

JVirtualVM 中线程有以下几种状态

作者: zhengaoly | 来源:发表于2021-12-01 16:17 被阅读0次

在 java 自带的工具 JVirtualVM 中线程有以下几种状态:

image

先说结论,各状态含义如下,后面有详细的 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 查看线程如下:

image

根据代码的顺序从上至下讲:

  • 两个运行或者监视线程的 System.out.println() 语句因为抢同一个 synchronize 锁,可以很明显的看出是在交替运行,状态分别处于运行监视状态。

  • 等待线程 synchronize 因为调用了 Object 的 wait 方法,一直处于等待状态。

  • 休眠线程省略。

  • 重点是和 reentrantLock 锁相关的三个线程,注意下上图中有一个地方写错了,等待线程 reentrantLock,实际应该是驻留线程 reentrantLock,可以看到无论是通过 condition 的 await 方法,还是在阻塞等待锁的过程中,都是处于驻留状态,而不是我一开始预想的等待状态,通过查看源码后发现它们最终都调用了 Unsafe 的 park 方法,后续的线程 dump 也能验证这一点。

  • pool- 1-threadpool-1 就是那个线程池,因为里面的线程处于空闲状态,也属于驻留

线程 dump

image.png

相关文章

  • JVirtualVM 中线程有以下几种状态

    在 java 自带的工具 JVirtualVM 中线程有以下几种状态: 先说结论,各状态含义如下,后面有详细的 d...

  • Java线程Thread解析

    线程的状态 简单的来说,线程可以分为以下几种状态: 新建 (new) 就绪 (runnable) 运行中 (run...

  • 线程状态与方法

    线程状态 对于线程来一般有以下几种状态 1. 创建状态(New) 每次我们新建线程例如,这种线程就处于创建状态 2...

  • java线程状态

    java的线程状态包括以下几种: NEW 线程创建的初始状态。 RUNABLE 线程正在执行。 注意这里是java...

  • 精选30道Java多线程面试题

    ​ 1、线程和进程的区别 2、实现线程有哪几种方式? 3、线程有哪几种状态?它们之间如何流转的? 4、线程中的st...

  • Android/Java 多线程分享

    这篇博客主要有以下几点 什么是线程,和进程的区别 线程有哪几种状态 线程安全的理解 volatile关键字,是线程...

  • 线程有几种状态?

  • java 中的 wait()方法和 sleep()方法的区别

    sleep()和wait()的区别 Java中的多线程是一种抢占式的机制而不是分时机制。线程主要有以下几种状态:可...

  • JVM中线程的状态转换图

    线程在一定条件下,状态会发生变化。线程一共有以下几种状态: 1.新建状态(new):新创建一个线程对象2.就绪状态...

  • 线程中的sleep()和wait();

    线程在一定条件下,状态会发生变化。线程一共有以下几种状态: 1、新建状态(New):新创建了一个线程对象。 2、就...

网友评论

      本文标题:JVirtualVM 中线程有以下几种状态

      本文链接:https://www.haomeiwen.com/subject/knisxrtx.html