【Java技术指南】「难点-核心-遗漏」Java线程状态流转及生命周期的技术指南(知识点串烧)!

简介: 【Java技术指南】「难点-核心-遗漏」Java线程状态流转及生命周期的技术指南(知识点串烧)!

前提介绍


本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理,配合这相关官方文档的中英文互译的介绍。



线程状态流转及生命周期


当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,它要经过新建(New)、就绪/可运行状态(Runnable)、阻塞(Blocked)和等待(Wait)、时间等待(Time_wait)、终止状态(Terminate)六种状态。尤其是当线程启动以后,它不能一直“霸占”着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换。


下图借鉴于官方网站:image.png



生命周期的六种状态


一个事物从出生的那一刻开始到最终死亡中间的整个过程.在事物的漫长的生命周期过程中,总会经历不同的状态(婴儿状态/青少年状态/中年状态/老年状态...).线程也是有生命周期的,也是存在不同的状态的,状态相互之间的转换。


线程对象的状态存放在Thread类的内部类(State)中:

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,
        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,
        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,
        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,
        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,
        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }
复制代码

注意:Thread.State类其实是一个枚举类.因为线程对象的状态是固定的,只有6种,此时使用枚举来表示是。


新建(new Thread)


  • 当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
  • 使用new创建一个线程对象,仅仅在堆中分配内存空间,在调用start方法之前。 新建状态下,线程压根就没有启动,仅仅只是存在一个线程对象而已.Thread t = new Thread();
  • 此时t就属于新建状态当新建状态下的线程对象调用了start方法,此时从新建状态进入可运行状态.线程对象的start方法只能调用一次,否则报错:IllegalThreadStateException.


例如
Thread  t1=new Thread();
复制代码

可运行(runnable)


分成两种子状态,ready和running。分别表示就绪状态和运行状态。



就绪状态


线程对象调用start方法之后,等待JVM的调度(此时该线程并没有运行),这时候线程处于等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行,换句话说线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。


运行状态


线程对象获得JVM调度,如果存在多个CPU,那么允许多个线程并行运行


image.png


  • 被转换成Terminated状态,比如调用 stop() 方法;
  • 被转换成Blocked状态,比如调用了sleep, wait 方法被加入 waitSet 中;
  • 被转换成Blocked状态,如进行 IO 阻塞操作,如查询数据库进入阻塞状态;
  • 被转换成Blocked状态,比如获取某个锁的释放,而被加入该锁的阻塞队列中;
  • 该线程的时间片用完,CPU 再次调度,进入Runnable状态;
  • 线程主动调用 yield 方法,让出 CPU 资源,进入Runnable状态



例如
t1.start();
复制代码


运行(running)他也从属于Runnable状态,但不在总体状态之内,属于逻辑状态机制


当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能,此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。


image.png


注意:image.png


Runnable状态的线程无法直接进入Blocked状态和Terminated状态的。只有处在Running状态的线程,换句话说,只有获得CPU调度执行权的线程才有资格进入Blocked状态和Terminated状态,Runnable状态的线程要么能被转换成Running状态,要么被意外终止。


堵塞(blocked)


正在运行的线程因为某些原因放弃CPU,暂时停止运行,就会进入阻塞状态.此时JVM不会给线程分配CPU,直到线程重新进入就绪状态,才有机会转到运行状态.阻塞状态只能先进入就绪状态,不能直接进入运行状态。


阻塞状态的两种情况:


  1. 当A线程处于运行过程时,试图获取同步锁时,却被B线程获取.此时JVM把当前A线程存到对象的锁池中,A线程进入阻塞状态.
  2. 当线程处于运行过程时,发出了IO请求时,此时进入阻塞状态.


由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。


image.png


  • 被转换成Terminated状态,比如调用 stop() 方法,或者是 JVM 意外 Crash;
  • 被转换成Runnable状态,阻塞时间结束,比如读取到了数据库的数据后;
  • 完成了指定时间的休眠,进入到Runnable状态;
  • 正在wait中的线程,被其他线程调用notify/notifyAll方法唤醒,进入到Runnable状态;
  • 线程获取到了想要的锁资源,进入Runnable状态;
  • 线程在阻塞状态下被打断,如其他线程调用了interrupt方法,进入到Runnable状态;


等待状态(waiting)


(等待状态只能被其他线程唤醒):


此时使用的无参数的wait方法,


  1. 当线程处于运行过程时,调用了wait()方法,此时JVM把当前线程存在对象等待池中.


计时等待状态(timed waiting)


(使用了带参数的wait方法或者sleep方法)


  1. 当线程处于运行过程时,调用了wait(long time)方法,此时JVM把当前线程存在对象等待池中.
  2. :当前线程执行了sleep(long time)方法.



终止状态(terminated)


通常称为死亡状态,表示线程终止.


  1. 正常执行完run方法而退出(正常死亡).
  2. 遇到异常而退出(出现异常之后,程序就会中断)(意外死亡).
  3. JVM 异常结束,所有的线程生命周期均被结束。

线程一旦终止,就不能再重启启动,否则报错(IllegalThreadStateException).



不推荐使用的线程方法


在Thread类中过时的方法(因为存在线程安全问题,所以弃用了):


  • void suspend() :暂停当前线程
  • void resume()  :恢复当前线程
  • void stop()  :结束当前线程

给大家结合官网在进行一个中文解释的状态流转图:


image.png






相关文章
|
3月前
|
安全 Java 编译器
揭秘JAVA深渊:那些让你头大的最晦涩知识点,从泛型迷思到并发陷阱,你敢挑战吗?
【8月更文挑战第22天】Java中的难点常隐藏在其高级特性中,如泛型与类型擦除、并发编程中的内存可见性及指令重排,以及反射与动态代理等。这些特性虽强大却也晦涩,要求开发者深入理解JVM运作机制及计算机底层细节。例如,泛型在编译时检查类型以增强安全性,但在运行时因类型擦除而丢失类型信息,可能导致类型安全问题。并发编程中,内存可见性和指令重排对同步机制提出更高要求,不当处理会导致数据不一致。反射与动态代理虽提供运行时行为定制能力,但也增加了复杂度和性能开销。掌握这些知识需深厚的技术底蕴和实践经验。
76 2
|
17天前
|
Java API 调度
Java 线程的生命周期
在JDK 1.5之前,线程的生命周期包括五种状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。JDK 1.5及之后增加了三种阻塞状态,共六种状态:新建、可运行、终止、锁阻塞、计时等待和无限等待。这些状态描述了线程在操作系统和JVM中的不同阶段。
Java 线程的生命周期
|
21天前
|
Java 调度
[Java]线程生命周期与线程通信
本文详细探讨了线程生命周期与线程通信。文章首先分析了线程的五个基本状态及其转换过程,结合JDK1.8版本的特点进行了深入讲解。接着,通过多个实例介绍了线程通信的几种实现方式,包括使用`volatile`关键字、`Object`类的`wait()`和`notify()`方法、`CountDownLatch`、`ReentrantLock`结合`Condition`以及`LockSupport`等工具。全文旨在帮助读者理解线程管理的核心概念和技术细节。
34 1
[Java]线程生命周期与线程通信
|
1月前
|
Java Python
python知识点100篇系列(16)-python中如何获取线程的返回值
【10月更文挑战第3天】本文介绍了两种在Python中实现多线程并获取返回值的方法。第一种是通过自定义线程类继承`Thread`类,重写`run`和`join`方法来实现;第二种则是利用`concurrent.futures`库,通过`ThreadPoolExecutor`管理线程池,简化了线程管理和结果获取的过程,推荐使用。示例代码展示了这两种方法的具体实现方式。
python知识点100篇系列(16)-python中如何获取线程的返回值
|
2月前
|
存储 消息中间件 资源调度
「offer来了」进程线程有啥关系?10个知识点带你巩固操作系统基础知识
该文章总结了操作系统基础知识中的十个关键知识点,涵盖了进程与线程的概念及区别、进程间通信方式、线程同步机制、死锁现象及其预防方法、进程状态等内容,并通过具体实例帮助理解这些概念。
「offer来了」进程线程有啥关系?10个知识点带你巩固操作系统基础知识
|
1月前
|
Java 数据库连接 数据库
不同业务使用同一个线程池发生死锁的技术探讨
【10月更文挑战第6天】在并发编程中,线程池是一种常用的优化手段,用于管理和复用线程资源,减少线程的创建和销毁开销。然而,当多个不同业务场景共用同一个线程池时,可能会引发一系列并发问题,其中死锁就是最为严重的一种。本文将深入探讨不同业务使用同一个线程池发生死锁的原因、影响及解决方案,旨在帮助开发者避免此类陷阱,提升系统的稳定性和可靠性。
47 5
|
1月前
|
Java 调度
Java一个线程的生命周期详解
Java中,一个线程的生命周期分为五个阶段:NEW(新建),RUNNABLE(可运行),BLOCKED(阻塞),WAITING(等待),TERMINATED(终止)。线程创建后处于新建状态,调用start方法进入可运行状态,执行中可能因等待资源进入阻塞或等待状态,正常完成或异常终止后进入终止状态。各状态间可相互转换,构成线程的生命周期。
|
1月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
61 0
|
1月前
|
安全 Java 编译器
Java基础-知识点(二)
Java基础-知识点(二)
13 0
|
1月前
|
存储 缓存 安全
Java基础-知识点(一)
Java基础-知识点(一)
16 0