Java多线程 (五)—— 线程的生命周期

article/2025/9/12 10:35:14

文章目录

  • 前言
  • 1、线程生命周期
    • 1.1、NEW(新建)
    • 1.2、RUNNABLE(可运行)
    • 1.3、BLOCKED(阻塞)
    • 1.4、WAITING(等待)
    • 1.5、TIMED_WAITING(计时等待)
    • 1.5、TERMINATED(被终止)
  • 2、线程生命周期流程图

前言

看过大多数博客,认为生命周期有5个阶段的,也有6个阶段的。总结了几篇,细分的话,线程的生命周期包含了6个阶段:
1、NEW(新建):线程刚被创建,但是未被启动;
2、RUNNABLE(可运行):线程已经调用start()等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行;
3、BLOCKED(阻塞):在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态,比如sleep()、wait()之后线程就处于了阻塞状态,这个时候需要其他机制将处于阻塞状态的线程唤醒,比如调用notify或者notifyAll()方法。唤醒的线程不会立刻执行run方法,它们要再次等待CPU分配资源进入运行状态;
4、WAITING(等待):正在等待另一个线程执行特定的动作的线程处于这个状态。
5、TIMED_WAITING(计时等待):正在等待另一个线程执行动作达到指定等待时间的线程处于这个状态。
6、TERMINATED(被终止):已退出的线程处于此状态。

注意:Java中将操作系统中断休眠状态分为了三种状态,也就是:BLOCKED、WAITING、TIMED_WAITING。只要 Java 线程处于这三种状态之一,那么这个线程就永远没有 CPU 的使用权。


1、线程生命周期

1.1、NEW(新建)

举个例子:

public class ThreadTest extends Thread{@Overridepublic void run() {}
}
//新建(new)一个线程
ThreadTest thread = new ThreadTest();

上面例子中new了一个线程对象。该线程就处于新建状态,还不能运行,此时JVM为其分配了内存,没有表现出任何线程的动态特征。

1.2、RUNNABLE(可运行)

可运行状态是个复合状态,可以再细分为两个状态:
(1)READY(就绪状态)
当线程对象调用了start()方法之后,该线程处于 就绪状态。处于就绪状态的线程位于线程队列中,此时它只是具备了运行的条件,能否获得CPU的使用权并开始运行,还需要等待系统的调度( 等待系统为其分配CPU时间片)。
(2)RUNNING(运行状态)
如果处于就绪状态的线程获得了CPU的使用权,并开始执行run()方法中的线程执行体,则该线程处于运行状态(即该线程从READY状态转变为RUNNING状态)。一个线程启动后,它可能不会一直处于运行状态,当运行状态的线程调用yield方法或使用完系统分配的时间后,系统就会剥夺该线程占用的CPU资源,让其他线程获得执行的机会(此时该线程又从RUNNING状态转变为READY状态)。需要注意的是,只有处于就绪状态的线程才可能转换到运行状态。

1.3、BLOCKED(阻塞)

阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
下面就列举一下线程由运行状态转换成阻塞状态的原因,以及如何从阻塞状态转换成就绪状态。
线程I/O:当线程调用了一个阻塞式的I/O方法时,该线程就会进入阻寒状态,如果想进入就绪状态就必须要等到这个阻塞的I/O方法返回。
线程同步锁(synchronized):当线程试图获取某个对象的同步锁时,如里该销被其他线程所持有,则当前线程会进入阻塞状态,如果想从阻塞状态进入就绪状态就必须获取到其他线程所持有的锁。

注意,线程从阻塞状态只能进入就绪状态,而不能直接进入运行状态,也就是说,结束阻塞的线程需要重新进入可运行池中,等待系统的调度。

1.4、WAITING(等待)

下面就列举一下线程由运行状态转换成等待状态的原因,以及如何从等待状状态转换成就绪状态。
线程等待:当线程调用了某个对象的wait()方法时,也会使线程进入等待状态,如果想进入就绪状态就需要使用notify()方法唤醒该线程。
线程加入:当在一个线程中调用了另一个线程的join()方法时,会使当前线程进入等待状态,在这种情况下,需要等到新加入的线程运行结束后才会结束等状态,进入就绪状态。

1.5、TIMED_WAITING(计时等待)

和WAITING 状态类似,区别在于状态的线程不会无限等待,如果在指定时间内完成了指定的操作,就会转换为 RUNNABLE状态。所以,在WATING方法中的大多数方法,只要加上一个时间参数,就会触发TIMED_WATING这个状态。具体如:Thread.currentThread().join(millis)、Thread.sleep(millis)、Obj.wait(timeout)等。

1.5、TERMINATED(被终止)

当线程顺利的完成run()方法中的任务,就会进入TERMINAL状态。同时,当线程抛出没有处理异常的时候,线程同样会变为TERMINAL状态。那如果业务上需要我们主动的终止线程,那应该怎么做呢?
可以通过调用线程的stop()、suspend()、resume()方法结束线程,但是这些方法早就已经被标记为过时方法,容易导致死锁,不推荐使用,推荐使用thread.interrupt();方来结束线程。

2、线程生命周期流程图

在这里插入图片描述


http://chatgpt.dhexx.cn/article/nayVuXQk.shtml

相关文章

线程的生命周期及五种基本状态

一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点。掌握了上图中的各知识点,Java中的多线程也就基本上掌握了。主要包括: Java线程具有五…

浅谈线程的生命周期

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态…

java中,线程的生命周期

java中,线程的生命周期 一、什么是线程? 见之前写的。 当线程启动后(线程对象调用start方法),它不能一直"独占"着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次…

JAVA 多线程并发

1.1.1. JAVA 并发知识库 1.1.2. JAVA 线程实现/创建方式 1.1.2.1. 继承 Thread 类 Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过 Thread 类的 start()实例方法。start()方法是一个 native 方法,它…

攻防世界 web高手进阶区 10分题 TimeKeeper

前言 继续ctf的旅程 开始攻防世界web高手进阶区的10分题 本文是TimeKeeper的writeup 解题过程 进入界面 惯例源码御剑 源码没发现 御剑扫到一个Flask debug console 先正常注册登录 尝试在注册和登录界面sqli 失败 没有别的头绪 就尝试研究debug 参考Flask debug pin安全问…

【Linux时钟系统】

Linux系统时间 时间设备![在这里插入图片描述](https://img-blog.csdnimg.cn/7c50db7d72ba4ff5a0f1264629769184.png)RTC时钟系统计时设备(吴斌个人主页)定时通知设备(吴斌个人主页)系统启动过程中的时钟系统SMP初始化阶段Linux时钟中断低精度定时器的使…

linux时间子系统 - clocksource/timekeeper

linux时间子系统中有一个很重要的记录时间的模块就是timekeeper,而timekeeper需要底层clock硬件设备的支持,每一个设备用结构体clocksource来表示,注册进系统的每一个clocksource会凭借优先级最终被选择成为timekeeper的时钟源。 1. clocksou…

【Java】Timer和TimerTask详解

以下内容根据 The JavaTM Tutorial 和相关API doc翻译整理,以供日后参考: 1.概览 Timer是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以计划执行一个任务一次或反复多次。 TimerTask一个抽象类,它的子类代表一个可以…

【Linux内核代码分析1】Linux时间子系统及HRTIMER实现

Linux时间子系统软件架构 (1)嵌入式设备需要较好的电源管理策略。传统的linux会有一个周期性的时钟,即便是系统无事可做的时候也要醒来,这样导致系统不断的从低功耗(idle)状态进入高功耗的状态。这样的设计…

Linux Time

1、Linux时钟框架 上图是linux时钟框架一个经典的描述。本质上linux各种时钟架构和服务是基于硬件提供的两种timer而构建的。 1、定时Timer 这类timer每个cpu都有一个独立的,称为local timer。这类timer的中断一般都是PPI(Private Peripheral Interrup…

Linux时间子系统基础(三):时间的维护者:timekeeper

本系列文章的前两节讨论了用于计时的时钟源:clocksource,以及内核内部时间的一些表示方法,但是对于真实的用户来说,我们感知的是真实世界的真实时间,也就是所谓的墙上时间,clocksource只能提供一个按给定频…

攻防世界--TimeKeeper

将price和id加上引号,触发debug 联想到扫描目录出现的/console Flask debug pin安全问题 这种方法有点难,换种方法 目录穿越 可以成功读取任意文件,获得flag。

html 时间控件滚动选择器,TimePicker

TimePicker滚动的列表选择器,可用于时间选择。多个TimePicker组合起来可实现复杂的应用,如效果图中,俩个TimePicker组合,一个表示"分"、一个表示"秒"。 效果图: 如何使用xml创建 android:id"…

Linux时间子系统之时间维护层(Time Keeper)

时间维护层会收到Tick层的周期调用,每次调用的周期是由内核参数决定的。在此期间,时间维护层可以读取时钟源设备的周期数,从而感知时间的流逝。 目前时间维护层主要负责维护以下几种类型的时间: 实时时间(CLOCK_REAL…

【Linux内核|时间子系统】Linux时间子系统(二)timekeeping简介

文章目录 1. timekeeping2. 计算墙上时间、启动时间差值3. timekeeper初始化3.1. 默认时钟源3.2. tk_setup_internals3.3. 设置时间 4. timekeeping_update4.1. tk_update_ktime_data:tkr_mono和tkr_raw设置4.2. update_fast_timekeeper4.3. shadow_timekeeper 1. t…

matlab 梯度下降 求偏导,通过计算图求梯度下降中各偏导的推导

通过计算图求梯度下降中各偏导的推导 Author: nex3z 2017-08-30 在 Neural Networks and Deep Learning 课程的 Logistic Regression Gradient Descent 一节以逻辑回归为例,介绍了使用计算图(Computation Graph)求梯度下降中各偏导的方法,但没有给出具体…

matlab|求导数/最值

本博文源于matlab求导数求极值求最值,涉及内容极限命令求导/diff求导/一元函数一阶导数,多阶导数,求参数导数/函数极值和最值/不给定区间求最值 用极限命令求导 例子:求函数3sinx4x^2在x0处的导数 >> syms t; limit((3*…

matlab 梯度下降 求偏导,吴恩达机器学习课程课时12梯度下降算法中参数θ0,θ1求偏导...

最近学习吴恩达的机器学习课程。 看到了线性回归的梯度下降算法。课程中将了一个非常简单的线性回归: 比如给出一些房子的size和对应的price,我们可以建立一个模型(在此模型就是线性回归), 希望之后在给出任意一个房子的size,可以…

matlab求COPULA偏导,matlab note

Update date:2018-01-05 Matlab Note 1 vine-copula 1.1 xlsread() 打开xlsx里面的数据 S3CE xlsread(电表建模数据.xlsx,S3CE,‘G2:G52’) 1.2常见希腊发音总结 image.png 3.prob() 连乘 由于matlab中的元素是以矩阵为单位,prod(x)就是把x向量中所有元…

matlab求解多元函数的偏导数diff

本博文源于matlab求解多元函数导数。涉及求一阶/求多阶/求向量偏导数/求隐函数导数 多元函数的偏导数 diff(f(x,y,z),变量名)例子 求x^2lny根号z的偏导数 >> syms x >> syms y >> syms z >> du_dx diff(x^2log(y)sqrt(z),x)du_dx 2*x>> du_dz…