线程生命周期及五种状态

article/2025/9/12 9:40:24

文章目录

  • 一、线程生命周期及五种状态
    • 1、New(初始化状态)
    • 2、Runnable(就绪状态)
    • 3、Running(运行状态)
    • 4、Blocked(阻塞状态)
    • 5、Terminated(终止状态)
  • 二、线程基本方法
    • 1、线程等待(wait)
    • 2、线程睡眠(sleep)
    • 3、线程让步(yield)
    • 4、线程中断(interrupt)
    • 5、join(等待其他线程终止)
    • 6、线程唤醒(notify)
    • 7、其他方法
  • 三、重点面试问题
    • 1、sleep和wait的区别:
    • 2、wait()、notify() 释放锁问题:

⭐️最全线程知识汇总篇(线程生命周期、线程池创建、线程池实现原理、线程基本方法)⭐️
⭐️ 如何创建一个线程?
⭐️ Java多线程之Executor框架
⭐️ 多线程分批处理数据

一、线程生命周期及五种状态

1、New(初始化状态)

用new语句创建的线程处于新建状态,此时它和其他Java对象一样,仅仅在堆区中被分配了内存。如:Thread t = new MyThread();

2、Runnable(就绪状态)

当调用线程对象的start()方法,线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,Java虚拟机会为它创建方法调用栈和程序计数器。处于这个状态的线程位于可运行池中,等待获得CPU的使用权,并不是说执行了start()此线程立即就会执行。

3、Running(运行状态)

当就绪状态中的线程获得了CUP执行资源,执行run()中的代码,这样的线程我们称为运行状态的线程。

4、Blocked(阻塞状态)

处于运行中的线程,由于某种原因放弃对cpu的使用权,处于阻塞状态,直到其进入就绪状态,才有机会再次被cpu调用进入运行状态。

根据阻塞原因不同,阻塞分为三种

  • 等待阻塞:运行状态中的线程执行wait方法,进入等待队列,等待阻塞;Java虚拟机就会把线程放到这个对象的等待池中;

  • 同步阻塞:线程获取同步锁失败(因为锁被其他线程占用),Java虚拟机就会把这个线程放到这个对象的锁池中;

  • 其他阻塞:通过调用sleep方法或者join方法或者发出I/O请求时,线程会进入阻塞状态,当sleep()状态超时,或者join()等待线程终止或者超时,或者I/O处理完毕,线程重新转入就绪状态;

5、Terminated(终止状态)

  • 正常结束,线程执行完

  • 异常退出
    异常退出,除了程序有问题导致的异常的退出,还可以使用共享变量的方式(定义个boolean标识等)退出,或者Interrupt中断线程,抛出异常,捕获异常break,跳出循环状态;

  • 调用stop(),会造成死锁,线程不安全,不建议使用

二、线程基本方法

1、线程等待(wait)

调用该方法,线程进入waiting状态,只有等待另外的线程通知或被中断才会返回,调用wait()后,会释放对象锁,因为wait方法一般用在同步方法或者同步代码块中。

2、线程睡眠(sleep)

强迫一线程睡 N毫秒,sleep不会释放当前锁,导致线程进入Timed-wating状态。

3、线程让步(yield)

yeild会使当前线程让出cpu执行时间片,与其他线程一起重新竞争cpu时间片,一般情况下,优先级高的先得到,但也不一定,有的系统对优先级不敏感。

4、线程中断(interrupt)

调用一个线程的interrupt() 方法中断一个线程,并不是强行关闭这个线程,仅仅是改变了内部维护的中断标识位,是线程固有的一个标识位。可以调用
在run内部根据thread.isIterrupted() 安全终止线程。

static方法isIterrupted() 判定当前线程是否处于中断状态:
1)如果一个正常线程,调用interrupt() ,是不能被打断的,打印中断标志位置为true;

public class TestIterruptedDemo1{public static void main (string[] args)throws InterruptedException {//创建线程t1Thread  t1=new Thread (()->if(Thread.currentThread.isInterrupted()){log.dubug("---------t1中断标识true,进来了---------");   }},name:"t1");t1.start();t1.interrupt();//没等t1启动,主线程先执行打断t1,将表示设置为true		}
}
t1还没有启动,主线程便执行了一个打断,即打断一个正常线程,则打印结果为true,将线程标记设置为true

控制台打印:

---------t1中断标识true,进来了---------"

2)如果一个sleep或者wait的线程,调用interrupt() ,方法则抛出InterruptedException( InterruptedException表示一个阻塞被中断了),线程的中断标志位会被复位成false;相当于用异常响应了这个中断,所以释放中断标志位。

public class TestIterruptedDemo2{public static void main (string[] args)throws InterruptedException {//创建线程t1Thread  t1=new Thread (()->try {log.dubug("---------t1启动,然后sleep---------");   TimeUnit.SECONDS.sleep(timeout:200); } catch (InterruptedException e) {log.dubug("---------t1被主线程打断了---------");   e.printStackTrace();} },name:"t1");t1.start();//主线程睡一下,主要是为了确保t1先执行,然后再打断sleep的t1TimeUnit.SECONDS.sleep(timeout:1);  t1.interrupt();//主线程1秒后醒来,打断t1		log.dubug("---------t1的打断标识是{}---------",t1.isInterrupted());   }
}

控制台打印:

---------t1启动,然后sleep---------
---------t1被主线程打断了---------
---------t1的打断标识是false---------

5、join(等待其他线程终止)

当前线程调用join(),则线程转为阻塞状态,eg:A线程中插入了B.join(),则B先执行,执行完,A线程继续执行;常见的是主线程生成并启动了子线程,需要用到子线程返回结果的场景;

6、线程唤醒(notify)

Object类中的notify唤醒在此对象监视器上等待的单个线程;
notifyAll唤醒在此对象监视器上等待的所有线程;

7、其他方法

  • isAlive判断一个线程是否存活;
  • activeCount 程序中活跃的线程数;
  • currentThread得到当前线程;
  • setPriority设置一个线程的优先级;
  • getPriority获取一个线程的优先级;
  • isDaemon线程是否为守护线程;

小结:方法wait(), notify()和notifyAll()被定义在Object 类里;
Thread类的sleep()和yield ()方法是静态的;
wait(), notify()和notifyAll ()必须在同步方法或者同步块中被调用

三、重点面试问题

1、sleep和wait的区别:

sleep属于Thread类,让出cpu,但是监控状态依然保持者,指定时间到了,就会恢复运行;
wait属于Object类方法,释放对象锁,进入等待锁定池,需要notify()才能重新进入运行状态;

2、wait()、notify() 释放锁问题:

wait()会立刻释放synchronized(obj)中的obj锁,以便其他线程可以执行obj.notify()

但是notify()不会立刻立刻释放sycronized(obj)中的obj锁,必须要等notify()所在线程执行完synchronized(obj)块中的所有代码才会释放这把锁.yield(),sleep()不会释放锁。


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

相关文章

线程的生命周期和状态

线程的六种状态 线程的生命周期主要有以下六种状态: New(新创建)Runnable(可运行)Blocked(被阻塞)Waiting(等待)Timed Waiting(计时等待)Termin…

线程的生命周期以及其中的方法

文章目录 线程的生命周期线程的5种状态 线程的基本方法线程等待:wait 方法线程睡眠:sleep 方法线程让步:yield 方法线程中断:interrupt 方法线程加入:join 方法线程唤醒:notify 方法后台守护线程&#xff1…

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

文章目录 前言1、线程生命周期1.1、NEW(新建)1.2、RUNNABLE(可运行)1.3、BLOCKED(阻塞)1.4、WAITING(等待)1.5、TIMED_WAITING(计时等待)1.5、TERMINATED&…

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

一.线程的生命周期及五种基本状态 关于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*…