首页 > 编程语言 >Java线程状态及生命周期

Java线程状态及生命周期

时间:2024-09-13 09:55:54浏览次数:10  
标签:状态 生命周期 Java Thread WAITING TestClass state 线程

基础概念

Java线程在运行生命周期中的指定时刻只可能处于这6种不同状态的其中一个状态,分别是:

  • NEW:初始状态,这是线程被创建出来但没有被调用start()
  • RUNNABLE:运行状态,线程被调用了start()等待运行的状态。
  • BLOCKED:阻塞状态,等待
  • WAITING:等待状态,表示该线程需要等待其他线程做出一些特定动作(通知或中断)
  • TIME_WAITING:超时等待状态,可以在指定的时间后自行返回而不是像WAITING一样一直等待。
  • TERMINATED:终止状态,表示该线程已经运行完毕。
    在这里插入图片描述

具体生命周期为:

  • 线程创建之后它将处于 NEW(新建) 状态,调用 start() 方法后开始运行,线程这时候处于 READY(可运行) 状态。可运行状态的线程获得了 CPU 时间片(timeslice)后就处于 RUNNING(运行) 状态。这里可能还有一个操作系统级别的阻塞状态(例如,线程执行长时间文件读写操作)
  • 当线程执行 wait() join()等方法之后,线程进入 WAITING(等待) 状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态。
  • TIMED_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将线程置于 TIMED_WAITING 状态。当超时时间结束后,线程将会返回到 RUNNABLE 状态。
  • 当线程进入 synchronized 方法/块,但是锁被其它线程占有,这个时候线程就会进入 BLOCKED(阻塞) 状态。
  • 线程在执行完了 run()方法之后将会进入到 TERMINATED(终止) 状态。

注意
图中的RUNNABLE种还有一个阻塞状态,这并不是Java线程中的阻塞状态,而是操作系统级别的阻塞状态。那会在什么情况下出现呢?比如耗时的文件IO时,操作系统其实会将线程置为阻塞,这时其实也是RUNNING。

代码实践

我们可以通过代码来查看上面图中出现的6种状态:

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TestClass {
    public static void main(String[] args) {
        // NEW
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                log.debug("running...");
            }
        };

        // RUNNABLE
        Thread t2 = new Thread("t2") {
            @Override
            public void run() {
                while (true) {

                }
            }
        };
        t2.start();

        // TERMINATED
        Thread t3 = new Thread("t3") {
            @Override
            public void run() {
                // log.debug("running...");
            }
        };
        t3.start();

        // TIMED_WAITING
        Thread t4 = new Thread("t4") {
            @Override
            public void run() {
                synchronized (TestClass.class) {
                    try {
                        sleep(100000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t4.start();

        // WAITING
        Thread t5 = new Thread("t5") {
            @Override
            public void run() {
                try {
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t5.start();

        // BLOCKED
        Thread t6 = new Thread("t6") {
            @Override
            public void run() {
                synchronized (TestClass.class) {
                    try {
                        sleep(100000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t6.start();


        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        log.debug("t1 state {}", t1.getState());
        log.debug("t2 state {}", t2.getState());
        log.debug("t3 state {}", t3.getState());
        log.debug("t4 state {}", t4.getState());
        log.debug("t5 state {}", t5.getState());
        log.debug("t6 state {}", t6.getState());

        Thread thread = new Thread(() -> {

        });
    }
}

查看控制台:

12:53:59.304 [main] DEBUG com.grq.threadState.TestClass - t1 state NEW
12:53:59.309 [main] DEBUG com.grq.threadState.TestClass - t2 state RUNNABLE
12:53:59.309 [main] DEBUG com.grq.threadState.TestClass - t3 state TERMINATED
12:53:59.309 [main] DEBUG com.grq.threadState.TestClass - t4 state TIMED_WAITING
12:53:59.309 [main] DEBUG com.grq.threadState.TestClass - t5 state WAITING
12:53:59.309 [main] DEBUG com.grq.threadState.TestClass - t6 state BLOCKED

标签:状态,生命周期,Java,Thread,WAITING,TestClass,state,线程
From: https://blog.csdn.net/qq_52127701/article/details/142095921

相关文章

  • JavaScript之填充数组的五种方法
    点击跳转填充字符串方法填充数组是一种常见的操作,尤其是当你需要初始化数组或填充默认值时。本文将介绍几种不同的方法来填充数组,每种方法都有其适用的场景和用法。1.使用Array.prototype.fill()fill()方法是最直接的填充数组的方式。它可以用指定的值填充数组的所有......
  • 线程池的应用-->2
    1.自定义线程工程当需要自定义线程的名字,线程的优先级,精灵线程状态时,需要自定义线程工厂。如何自定义线程工厂自定义工厂类,实现ThreadFactory接口,重写方法newThread()在创建线程池对象时,传递上述线程工厂对象publicclassTest5{publicstaticvoidmain(Strin......
  • 2.Java面向对象第二章方法与方法重载
    2.Java面向对象第二章方法与方法重载文章目录2.Java面向对象第二章方法与方法重载一、方法参数传递二、值传递与引用传递三、数组,对象参数传递四、构造方法五、this六、方法重载七、成员变量和局部变量的区别一、方法参数传递方法语法:访问修饰符返回值类型......
  • 3.Java面向对象第三章封装与继承
    3.Java面向对象第三章封装与继承文章目录3.Java面向对象第三章封装与继承一、封装二、包三、访问权限四、static静态五、继承一、封装什么是封装:隐藏类的内部实现细节,对外提供一个可以访问的接口。步骤:1.设置属性为private2.生成get和set方法3.可以在get或se......
  • 线程池介绍、参数、执行过程
    线程池管理一系列线程的资源池,提供了一种限制和管理线程资源的方式线程池一般用于执行多个不相关联的耗时任务,没有多线程的情况下,任务顺序执行,使用了线程池的话可让多个不相关联的任务同时执行好处降低资源消耗:频繁的线程创建和销毁会消耗系统资源,线程池可以复用已经创建......
  • 基于java的餐厅点餐订餐餐桌预订系统JAVA.JSP【论文、源码、实训报告】
     博主介绍:......
  • 《深入理解 Java 中的 super 关键字》
    目录一、为什么需要super?二、super的理解及可调用结构(一)super是对父类的引用(二)super调用构造器三、子类对象实例化全过程一、为什么需要super?子类继承父类以后,可能会对父类的方法进行重写。在这种情况下,有时候我们需要在子类中调用父类中被重写的方法。此外,如果子类和......
  • 【Java】—— Java面向对象高级:抽象类与抽象方法(或abstract关键字)
    目录6.抽象类与抽象方法(或abstract关键字)6.1由来6.2语法格式6.3使用说明6.4注意事项练习:工资系统设计(1)MyDate类包含:(2)定义一个Employee类,该类包含:(3)定义SalariedEmployee类继承Employee类,(4)参照SalariedEmployee类定义HourlyEmployee类,(5)定义PayrollSystem类,......
  • JAVA基础知识
    JAVA版本(Oracle甲骨文)标准版(JZSE)微缩版(JZME)企业版(JZEE)JAVA特性跨平台、安全、简单、面向对象(封装、继承、多态)、动态特性、分布式JDK(JAVA开发工具)---JRE(JAVA运行环境)---JVE(JAVA虚拟机)JVM是可运行java字节码的假想计算机基于下层操作系统和硬件平台功能:执行代码、管理内......
  • Java面试笔记记录6
    1.Spring是什么?特性?有哪些模块?Spring是一个轻量级、非入侵式的控制反转Ioc和面向切面AOP的框架。特性:1.Ioc和DISpring的核心就是一个大的工厂容器,可以维护所有对象的创建和依赖关系,Spring工厂用于生成Bean,并且管理Bean的生命周期,实现高内聚低耦合的设计理念。2.AOP编程Sp......