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状态恢复,继续执行。

相关推荐
2301_780789666 小时前
跨平台适配!SDK 游戏盾兼容全终端游戏场景
java·网络·ddos
学长毕设7 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
步行cgn8 小时前
FormHttpMessageConverter 详解:Spring MVC 中表单数据的读写转换器
java·spring·mvc
龙亘川8 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
金銀銅鐵8 小时前
[Java] 用 CLI 展示 EnumMap 增删键值对时的内部变化
java·源码·ai编程
秋天的怀念_David8 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Raas1009 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
niucloud-admin9 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php
霸道流氓气质10 小时前
智能客服组件:分层意图识别、RAG Advisor 与人工转接状态机的 Vue3 + Spring AI 生产级实战
java·人工智能·spring
captain37610 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis