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

相关推荐
lemon_sjdk2 小时前
LWJGL教程(2)——游戏循环
java·人工智能·算法·游戏
weixin_524749963 小时前
MVCC(多版本并发控制)介绍及实现原理
java·数据库
skylijf3 小时前
C++ Primer(第5版)- Chapter 7. Classes -004
java·开发语言
泉城老铁3 小时前
springboot+druid预防连接断开、断开后自动恢复
java·后端·架构
m1cr0wave3 小时前
javaweb的几大常见漏洞
java·安全·web
泉城老铁3 小时前
Spring Boot 中使用 Druid 连接池进行极致优化
java·后端·架构
Reggie_L4 小时前
JVM-Java
java·jvm·python
何中应4 小时前
EasyExcel使用
java·后端·excel
智_永无止境4 小时前
FastExcel:革新Java生态的高性能Excel处理引擎
java·excel·fastexcel
巴拉巴巴巴拉4 小时前
Maven 配置文件核心配置:本地仓库、镜像与 JDK 版本
java·开发语言·maven