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

相关推荐
workflower3 小时前
单元测试-例子
java·开发语言·算法·django·个人开发·结对编程
YuanlongWang3 小时前
C# 基础——装箱和拆箱
java·开发语言·c#
b78gb3 小时前
电商秒杀系统设计 Java+MySQL实现高并发库存管理与订单处理
java·开发语言·mysql
wb043072014 小时前
性能优化实战:基于方法执行监控与AI调用链分析
java·人工智能·spring boot·语言模型·性能优化
天若有情6735 小时前
Java Swing 实战:从零打造经典黄金矿工游戏
java·后端·游戏·黄金矿工·swin
lichong9516 小时前
Android studio 修改包名
android·java·前端·ide·android studio·大前端·大前端++
lichong9516 小时前
Git 检出到HEAD 再修改提交commit 会消失解决方案
java·前端·git·python·github·大前端·大前端++
@yanyu6666 小时前
Tomcat安装与HTML响应实战
java·tomcat·html
Chen-Edward7 小时前
有了Spring为什么还有要Spring Boot?
java·spring boot·spring
陈小桔8 小时前
idea中重新加载所有maven项目失败,但maven compile成功
java·maven