Java基础夯实——2.4 线程的生命周期

在这里插入图片描述

Java线程生命周期

Java线程的生命周期分为:新建(New)就绪(Runnable)阻塞(Blocked)等待 (Waiting)计时等待(Timed_Waiting)终止(Terminated) 六种状态,这些状态通过Thread.State枚举类定义。

1. 新建状态(New)

  • 当一个线程对象被创建但尚未调用start()方法时,线程处于新建状态

  • 在这个阶段,线程对象仅存在于内存中,但尚未与操作系统的底层线程关联。

  • 可以为线程设置名称、优先级等属性,但线程未开始执行。

  • 状态特点

    • 调用start()方法后会转移到就绪状态
    • 如果没有调用start()方法就试图调用join()interrupt(),将抛出异常。
  • 示例

public class ThreadLifecycleExample {public static void main(String[] args) {Thread thread = new Thread(() -> System.out.println("Thread is running."));// 线程处于新建状态System.out.println("Thread State: " + thread.getState()); // 输出 NEW}
}

2. 就绪状态(Runnable)

  • 调用start()方法后,线程进入就绪状态

  • 此时线程已交给操作系统线程调度器管理,但未必立即运行。

  • 线程调度器根据算法(如时间片轮转)决定何时将线程分配到CPU。

  • 状态特点

    • 此状态不等同于“运行中”,线程可能随时等待被调度。
    • 调用start()后,无法再次调用该方法,否则会抛出IllegalThreadStateException
  • 示例

public class ThreadLifecycleExample {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println("Thread is running.");});thread.start();System.out.println("Thread State after start(): " + thread.getState()); // 输出 RUNNABLE}
}

3. 运行状态(Running)

  • 当线程获得CPU时间片后,线程进入运行状态

  • 此时线程执行其run()方法中的任务。

  • 线程调度器可能在运行状态下暂停线程,并将其转移回就绪状态以让其他线程运行。

  • 状态特点

    • 开发者无法显式设置线程为运行状态,状态完全由操作系统调度决定。
    • 多线程环境下,运行状态的线程可能随时被挂起。
  • 代码示例

public class ThreadLifecycleExample {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println("Thread State: " + Thread.currentThread().getState()); // 输出 RUNNABLE 或运行中});thread.start();}
}

4. 等待/阻塞/计时等待状态

线程可能因资源或时间限制无法继续运行时,会进入以下三种状态:

(1)等待状态(Waiting)

  • 线程无限期地等待另一个线程唤醒它。

  • 通常是通过Object.wait()Thread.join()进入。

  • 唤醒方式包括调用notify()notifyAll()

  • 状态特点

    • 无法自行恢复,必须由另一个线程显式唤醒。
    • 常用于线程间协作。
  • 示例

public class WaitingExample {public static void main(String[] args) throws InterruptedException {Object lock = new Object();Thread thread = new Thread(() -> {synchronized (lock) {try {System.out.println("Thread is waiting.");lock.wait(); // 线程进入等待状态} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread resumed.");}});thread.start();Thread.sleep(1000); // 主线程暂停1秒synchronized (lock) {lock.notify(); // 唤醒等待线程}}
}

(2)计时等待状态(Timed Waiting)

  • 线程等待一段时间后会自动唤醒。

  • 调用如Thread.sleep()join(timeout)wait(timeout)方法会进入该状态。

  • 状态特点

    • 无需显式唤醒,时间结束后线程自动进入就绪状态
    • 常用于延时操作。
  • 示例

public class TimedWaitingExample {public static void main(String[] args) {Thread thread = new Thread(() -> {try {System.out.println("Thread is sleeping.");Thread.sleep(2000); // 线程进入计时等待状态System.out.println("Thread woke up.");} catch (InterruptedException e) {e.printStackTrace();}});thread.start();}
}

(3)阻塞状态(Blocked)

  • 当一个线程试图进入被其他线程持有的同步代码块时,会进入阻塞状态。

  • 一旦锁被释放,线程将进入就绪状态等待调度。

  • 状态特点

    • 阻塞是由于线程竞争共享资源而导致的。
    • 常见于synchronized关键字或锁机制。
  • 示例

public class BlockedExample {public static void main(String[] args) {Object lock = new Object();Thread thread1 = new Thread(() -> {synchronized (lock) {try {Thread.sleep(5000); // 保持锁5秒} catch (InterruptedException e) {e.printStackTrace();}}});Thread thread2 = new Thread(() -> {synchronized (lock) {System.out.println("Thread 2 acquired the lock.");}});thread1.start();thread2.start();}
}

5. 终止状态(Terminated)

  • 描述

    • 当线程执行完成或因异常退出时,进入终止状态
    • 终止后的线程无法再次启动。
  • 状态特点

    • 使用isAlive()方法可以检查线程是否仍存活。
    • 线程终止后,它的资源会被JVM回收。
  • 代码示例

public class TerminatedExample {public static void main(String[] args) {Thread thread = new Thread(() -> System.out.println("Thread is running."));thread.start();try {thread.join(); // 等待线程终止} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread State: " + thread.getState()); // 输出 TERMINATED}
}

常见问题

1. 线程的生命周期包括哪几个阶段?**

New : 为线程分配内存并初始化其成员变量值
Runnable:JVM完成方法调用栈和程序计数器创建,等待线程调用和运行
Blocked:主动或被动放弃CPU使用权并暂停运行
Waiting:等待
Timed_Waiting:超时后会被自动唤醒
Terminated:正常或者异常结束或者手动结束

2. 在哪些情况下会出现线程阻塞?

线程阻塞(Blocked)通常发生在以下几种场景中:

  1. 等待锁:
    • 一个线程试图进入由synchronized关键字保护的代码块或方法,但锁已被其他线程持有,当前线程将进入阻塞状态。
    • 示例:
      synchronized (lock) {// 当前线程执行时,其他线程试图进入会阻塞
      }
      
  2. I/O操作:
    • 线程等待输入/输出完成时,如从文件或网络读取数据。
  3. 线程阻塞工具类:
    • 使用Lock或类似机制时,线程可能因为未能获取锁而被阻塞。
    • 示例:
      Lock lock = new ReentrantLock();
      lock.lock(); // 其他线程会在这里阻塞
      
  4. 其他同步机制:
    • 使用CountDownLatchSemaphore等并发工具,线程可能会因未满足条件而阻塞。

3. 线程在就绪状态下会立即执行吗?

不会 线程处于就绪状态时,已经准备好运行,但是否执行取决于线程调度器的安排。
线程调度器根据操作系统的调度策略(如时间片轮转或优先级)决定何时将线程分配到CPU。
如果有多个线程处于就绪状态,它们需要等待调度。

4. 什么是线程阻塞?

**线程阻塞(Blocked)**是指线程因为某种原因被挂起,无法继续执行,直到某些条件满足为止。

  • 触发原因:
    1. 等待锁: 线程试图进入被其他线程持有的synchronized代码块或方法。
    2. 资源不可用: 线程等待特定资源(如文件、网络数据)。
    3. 线程竞争: 线程因并发控制工具(如锁、信号量)而受阻。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/474718.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java Springboot二手书籍交易系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 数据…

【Mac】未能完成该操作 Unable to locate a Java Runtime

重生之我做完产品经理之后回来学习Data Mining Mac打开weka.jar报错"未能完成该操作 Unable to locate a Java Runtime" 1. 打开终端执行 java -version 指令,原来是没安装 JDK 环境 yyzccnn-mac ~ % java -version The operation couldn’t be comple…

【大语言模型】ACL2024论文-12 大型语言模型的能力如何受到监督式微调数据组成影响

【大语言模型】ACL2024论文-12 大型语言模型的能力如何受到监督式微调数据组成影响 论文:https://arxiv.org/pdf/2310.05492 目录 文章目录 【大语言模型】ACL2024论文-12 大型语言模型的能力如何受到监督式微调数据组成影响论文:https://arxiv.org/p…

刷题强训(day09)【C++】添加逗号、跳台阶、扑克牌顺子

目录 1、添加逗号 1.1 题目 1.2 思路 1.3 代码实现 2、 跳台阶 2.1 题目 2.2 思路 2.3 代码实现 dp 滚动数组 3、扑克牌顺子 3.1 题目 3.2 题目 3.3 代码实现 1、添加逗号 1.1 题目 1.2 思路 读完题,我们知道了要将一个数的每三位用逗号分割。 所以…

华为再掀技术革新!超薄膜天线设计路由器首发!

随着Wi-Fi技术的不断进步,新一代的Wi-Fi 7路由器凭借其高速率、低延迟、更稳定的性能受到了广泛关注。它能够更好地满足现代家庭对网络性能的高要求,带来更加流畅、高效的网络体验。9月24日,华为在其秋季全场景新品发布会上推出了全新Wi-Fi 7…

leetcode:344. 反转字符串(python3解法)

难度:简单 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1: 输入:s [&qu…

【蓝桥杯C/C++】深入解析I/O高效性能优化:std::ios::sync_with_stdio(false)

文章目录 💯前言💯C 语言与 C 语言的输入输出对比1.1 C 语言的输入输出1.2 C 语言的输入输出 💯 std::ios::sync_with_stdio(false) 的作用与意义2.1 什么是 std::ios::sync_with_stdio(false)2.2 使用 std::ios::sync_with_stdio(false) 的示…

学习threejs,通过SkinnedMesh来创建骨骼和蒙皮动画

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.SkinnedMesh 蒙皮网格…

移门缓冲支架的工作原理

移门缓冲支架是一种安装在滑动门上的装置,主要用于吸收门关闭时的冲击力,防止门突然停止时的震动,从而保护门体、轨道和墙体。 1. 液压缓冲液压缓冲支架利用液体通过狭窄通道时产生的阻力来减缓门的运动。当门关闭时,液压油被迫通…

MySQL 日志 主从复制

1. 日志 学习链接,click mysql中有4种日志: 错误日志二进制日志查询日志慢查询日志 1.1 错误日志 错误日志是MySQL中最重要的日志之一,它记录了当mysqld启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息。当…

《设计模式》创建型模式总结

目录 创建型模式概述 Factory Method: 唯一的类创建型模式 Abstract Factory Builder模式 Prototype模式 Singleton模式 最近在参与一个量化交易系统的项目,里面涉及到用java来重构部分vnpy的开源框架,因为是框架的搭建,所以会涉及到像…

【支持向量机(SVM)】:相关概念及API使用

文章目录 1 SVM相关概念1.1 SVM引入1.1.1 SVM思想1.1.2 SVM分类1.1.3 线性可分、线性和非线性的区分 1.2 SVM概念1.3 支持向量概念1.4 软间隔和硬间隔1.5 惩罚系数C1.6 核函数 2 SVM API使用2.1 LinearSVC API 说明2.2 鸢尾花数据集案例2.3 惩罚参数C的影响 1 SVM相关概念 1.1…

某校园网登录界面前端加密绕过

前言 尝试对学校校园网登录框进行爆破,发现密码在前端被加密了 Burp抓包 抓包信息 DDDDD2022***&upass3d5c84b6fb1dc75987884f39c05b0e6a123456782&R10&R21&para00&0MKKey123456&v6ip From表单提交上来的文本这些参数,DDDD是…

网络基础(3)https和加密

http其它的报头 直接看图片: 上图中的第一个和第二个类型之前已经使用过了也就不多做说明了,第三个报头类型使用的很少了。第四个报头类型主要就使用在一些灰度更新的应用上,确定用户使用的软件的版本不让其访问该版本不能访问的功能。下一个…

macOS 的目录结构

文章目录 根目录 (/)常见目录及其用途示例目录结构注意事项根目录 (/)主要目录及其含义其他目录总结 macOS 的目录结构无论是在 Intel 架构还是 ARM 架构的 Mac 电脑上都是相同的。macOS 的目录结构遵循 Unix 和 BSD 的传统,具有许多标准目录。以下是一些主要目录及…

【WPF】Prism学习(八)

Prism Dependency Injection 1.处理解析错误 1.1. 处理解析错误: 这个特性是在Prism 8中引入的,如果你的应用目标是早期版本,则不适用。 1.2. 异常发生的原因: 开发者可能会遇到多种原因导致的异常,常见的错误包括…

集群聊天服务器(11)客户端开发

目录 首页面功能开发添加好友和聊天帮助和添加好友聊天功能创建群组添加群组群组聊天退出 测试问题一对一聊天第一次发送两个离线消息只收到一个创建和加入群组 首页面功能开发 #include "json.hpp" #include <iostream> #include <thread> #include &l…

Pytest-Bdd-Playwright 系列教程(10):配置功能文件路径 优化场景定义

Pytest-Bdd-Playwright 系列教程&#xff08;10&#xff09;&#xff1a;配置功能文件路径 & 优化场景定义 前言一、功能文件路径的配置1.1 全局设置功能文件路径1.2. 在场景中覆盖路径 二、避免重复输入功能文件名2.1 使用方法2.2 functools.partial 的背景 三、应用场景总…

Cyberchef使用功能之-多种压缩/解压缩操作对比

cyberchef的compression操作大类中有大量的压缩和解压缩操作&#xff0c;每种操作的功能和区别是什么&#xff0c;本章将进行讲解&#xff0c;作为我的专栏《Cyberchef 从入门到精通教程》中的一篇&#xff0c;详见这里。 关于文件格式和压缩算法的理论部分在之前的文章《压缩…

Leetcode 回文数

下面是解决这个回文数问题的一个Java解法&#xff1a; 代码解释 特殊情况处理&#xff1a; 如果数字是负数&#xff0c;直接返回false&#xff0c;因为负数不可能是回文数。如果数字以0结尾&#xff0c;但不是0本身&#xff0c;也不可能是回文数&#xff08;例如10不是回文数…