Java线程状态详解

1. 线程的状态及变化

线程的状态反应了线程的一个生命周期,我们创建启动一个线程以后,线程处于就绪状态,当操作系统调度,使得线程获取到CPU时间片以后,线程处于执行状态,线程执行结束以后,线程处于终结状态。如果线程在执行过程中,竞争锁失败,则会进入阻塞状态;如果线程执行的代码中存在Object.wait()、Thread.join()方法时,线程会进入无限等待,即等待状态,需要其他线程帮助唤醒;如果线程执行的代码中只是因为存在Thread.sleep(n)、Object.wait(timedout)等带了超时时间方法而被阻塞时,线程处于超时阻塞状态。

就绪:在Java中,我们创建一个线程,执行start()方法后,线程处于就绪状态,因为此时还没有获得CPU时间片,没有真正开始执行。

运行:当线程经过操作系统调度获得CPU时间片以后,线程开始执行,线程进入运行状态。

阻塞:线程在执行代码过程中,存在竞争Synchronized、Lock锁的时候,如果经常失败,则线程进入阻塞状态,当线程获取到锁以后,线程重新进入就绪状态。

等待:线程在代码执行过程中,遇到Thread.join()、Object.wait()等方法后,线程进入等待状态。因Thread.join()方法阻塞的线程等待调用join()方法的线程执行结束以后,会进入就绪状态。因Object.wait()方法方法阻塞的线程,需要其他线程执行Object.notify()或者Object.notifyAll()方法来唤醒,不过唤醒后应该进入的是阻塞状态,因为可能还没拿到对应的锁。

超时等待:线程在代码执行过程中,遇到Thread.sleep(n)、Object.wait(timedout)方法后,会进入超时等待状态,到达设定的时间后,线程会进入就绪状态,等待执行

2. 线程是如何进入各种状态的?

现在我们已经知道如何构建和启动一个线程,现在通过几段代码演示一下线程如何进入各种状态。

RUNNABLE状态

java 复制代码
private static Object object = new Object();

static void runnableState() throws InterruptedException {
        Thread t = Thread.ofVirtual().start(() -> {
            System.out.println("thread status is " + Thread.currentThread().getState());
        });
        t.join();
}

BLOCKED

java 复制代码
static void blockState() throws InterruptedException {
        Thread t1 = Thread.ofVirtual().name("t1_Thread").start(() -> {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + " status is " + Thread.currentThread().getState());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }

        });

        Thread.sleep(100);

        Thread t2 = Thread.ofVirtual().name("t2_Thread").start(() -> {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + " start run , status is " + Thread.currentThread().getState());
            }

        });

        // 这里需要加这一句,不然t2启动后可能还没开始竞争锁,导致下面输出的t2的状态是 RUNNABLE
        Thread.sleep(100);

        System.out.println(t2.getName() + " status is " +t2.getState());

        t1.join();
        t2.join();
}

这里t1线程获取锁之后,被Thread.sleep(1000)阻塞住,导致t2线程暂时拿不到锁,t2线程的状态为BLOCKED

WAITTING

java 复制代码
static void waittingThread() throws InterruptedException {
        Thread t = Thread.ofVirtual().name("t_thread").start(()->{
            // 这里必须用synchronized修饰,wait要和synchronized配合使用
            synchronized (object){
                try {
                    object.wait();
                    System.out.println(Thread.currentThread().getName() + " pass wait ");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        Thread.sleep(100);

        System.out.println(t.getName() + " status is " +t.getState());

        Thread.ofVirtual().start(()->{
            synchronized (object){
                object.notify();
            }
        });
        Thread.sleep(100);

        System.out.println(t.getName() + " status is " +t.getState());

        t.join();
}

这里线程t执行到object.wait()时,线程会停止执行,并处于WAITTING状态,直到下面有新的线程执行了object.notify(),线程t才会恢复运行。

TIMED_WAITING

java 复制代码
 static void timedoutWaitThread() throws InterruptedException {
        Thread t = Thread.ofVirtual().name("t_thread").start(()->{
            synchronized (object){
                try {
                    object.wait(100);
                    System.out.println(Thread.currentThread().getName() + " pass time_wait ");
                    System.out.println(Thread.currentThread().getName()  + " status is " + Thread.currentThread().getState());
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        Thread.sleep(50);

        System.out.println(t.getName() + " status is " +t.getState());

        t.join();
    }

这里线程t执行到object.wait(100)时,线程会停止执行,并处于TIMED_WAITING 状态,因为object.wait(100)设置了100毫秒的等待时间,100毫秒后,线程自动从TIMED_WAITING状态恢复,继续执行。

相关推荐
主宰者21 分钟前
C# CommunityToolkit.Mvvm全局事件
java·前端·c#
计算机学姐42 分钟前
基于SpringBoot的咖啡店管理系统【个性化推荐+数据可视化统计+配送信息】
java·vue.js·spring boot·后端·mysql·信息可视化·tomcat
My的梦想已实现1 小时前
关于JAVA Springboot集成支付后打包JAR之后报安全错误的处理
java·spring boot·jar
ooseabiscuit1 小时前
SpringBoot3整合FastJSON2如何配置configureMessageConverters
java
ok_hahaha1 小时前
java从头开始-黑马点评-Redission
java·开发语言
无巧不成书02181 小时前
Java面向对象零基础实战:从Employee类吃透自定义类核心,掌握封装精髓
java·开发语言·java入门·面向对象·自定义类·employee类·java核心技术
小江的记录本1 小时前
【注解】常见 Java 注解系统性知识体系总结(附《全方位对比表》+ 思维导图)
java·前端·spring boot·后端·spring·mybatis·web
跃上青空2 小时前
Java如何优雅的使用fastjson2进行枚举序列化/反序列化,欢迎探讨
java·开发语言
Mr.45672 小时前
Spring Boot 集成 PostgreSQL 表级备份与恢复实战
java·spring boot·后端·postgresql
架构师沉默2 小时前
为什么一个视频能让全国人民同时秒开?
java·后端·架构