自学内容网 自学内容网

线程状态以及切换条件

在正式开始了解线程之前,有一个东西可以关注线程的状态,那就是jconsole,这个东西也并不需要我们再次去下载,因为这个jconsole是Java(JDK)自带的一款图形化监控和管理工具

首先我们得找到我们的JDK装在哪里,找到之后选择bin目录,点进去找到一个名为 jconsole.exe的可执行文件并运行,运行之后我们可以看到下面这张图,我们选择自己要要查看的进程(注意这里的进程必须是正在运行的状态)然后点击连接,进去之后呢,点击左上角的线程,并在这些线程中找到自己要查看的那条线程就好了

线程一共有几种

1.NEW(新建)

  • 含义:线程已经被创建,但尚未启动。即调用了Thread类的构造方法,但还没有调用start()方法。
        Thread myNewThread = new Thread(()->{
            System.out.println("当前线程名称"+Thread.currentThread().getName());
        });

        System.out.println(myNewThread.getState());

2.RUNNABLE(可运行)

  • 就绪: 线程已经获得了所有执行所需资源(比如CPU时间片、内存等),等待CPU调度执行,但可能还没开始运行。
  • 运行中: 线程正处于执行状态,正在占用CPU资源进行任务处理。
        Thread myRunnableThread = new Thread(()->{
            System.out.println("当前线程名称"+Thread.currentThread().getName());
        });

        myRunnableThread.start();
        System.out.println(myRunnableThread.getState());

3.TERMINATED(终止)

  • 含义:线程已经执行完毕或因异常终止。
        Thread t = new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        t.start();
        System.out.println("t线程开始执行");
        t.join();
        System.out.println("t线程执行完毕");
        System.out.println(t.getState());

4.WAITING(等待)

  • 含义:线程因为调用了Object.wait()方法,或者Thread.join()方法,或者LockSupport.park()方法,并且没有指定等待时间,导致线程等待。
        final Object object = new Object();
        Thread t1 = new Thread(()->{
            try {
                synchronized(object){
                    System.out.println("wait开始等待");
                    object.wait();
                    System.out.println("wait等待结束");
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        },"t1");
        t1.start();

        Thread t2 = new Thread(()->{
            synchronized(object){
                System.out.println("notify开始执行");
                Scanner scanner = new Scanner(System.in);
                scanner.next();
                object.notify();
                System.out.println("notify执行完毕");
            }
        },"t2");
        t2.start();

我们可以用通过 jconsole 来观察到 这个线程状态

当我们执行这段代码,并且在输入环节还未按下Enter键的时候,此时 t1 线程就处于waiting状态

5.TIMED_WAITING(定时等待) 

  • 含义:与WAITING相似,不过线程在等待一个具体的时间,即调用了带有超时参数的Object.wait(long timeout)Thread.sleep(long millis), 或者Thread.join(long millis)等方法。
        final Object object = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(object){
                    while(true){
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        },"t1");
        t1.start();
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object){
                    System.out.println("hehe");
                }
            }
        },"t2");
        t2.start();

使⽤ jconsole 可以看到 t1 的状态是 TIMED_WAITING , t2 的状态是 BLOCKED

这里是t1线程的执行流程:

  1. t1线程启动,并尝试获取object对象的锁。
  2. 一旦获取了锁,t1线程就会进入一个无限循环,在这个循环中,它会调用Thread.sleep(1000)
  3. 调用Thread.sleep(1000)会使t1线程暂停执行1000毫秒,并且线程的状态会变为TIMED_WAITING
  4. 1000毫秒过后,t1线程会自动从TIMED_WAITING状态变为RUNNABLE状态,并继续执行循环中的代码。

与此同时,t2线程也在尝试获取object对象的锁。但是,由于t1线程已经持有了这个锁,并且由于无限循环和sleep调用,它不会很快释放这个锁,所以t2线程将不得不等待,直到t1线程释放锁(在这个特定的代码示例中,实际上t1线程永远不会释放锁,因为它没有退出同步块的路径)。

6.BLOCKED(阻塞)

  • 含义:线程在等待监视器锁,以便进入一个同步块或方法。例如,当线程试图获取一个内部的对象锁,而锁被其他线程持有时,线程就会进入BLOCKED状态。
        final Object object = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(object){
                    while(true){
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        },"t1");
        t1.start();
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object){
                    System.out.println("hehe");
                }
            }
        },"t2");
        t2.start();

此处代码和上面 TIMED_WAITING 的代码是一样的,同理t1 的状态是 TIMED_WAITING , t2 的状态是 BLOCKED,其他的可以参考上面,这里就不过多赘述了

状态之间的切换条件

  • NEW -> RUNNABLE:当调用线程的start()方法时,线程状态从NEW变为RUNNABLE。

  • RUNNABLE -> BLOCKED:当线程试图获取一个内部的对象锁,而锁被其他线程持有时。

  • RUNNABLE -> WAITING:当线程调用Object.wait()方法,没有指定等待时间。

  • RUNNABLE -> TIMED_WAITING:当线程调用如Thread.sleep(long millis)Object.wait(long timeout)等带超时参数的方法。

  • WAITING/TIMED_WAITING -> RUNNABLE:当等待条件满足,如wait()方法被其他线程调用notify()notifyAll()唤醒,或sleep()join()park()超时/被unpark。

  • RUNNABLE -> TERMINATED:当线程执行完毕其run()方法,或者线程因未捕获的异常而结束。


原文地址:https://blog.csdn.net/snow_feather/article/details/140569526

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!