【面试题-009】线程的生命周期和状态

文章目录

  • java如何创建线程
      • 继承 `Thread` 类
      • 使用 `Runnable` 接口
      • 选择继承还是实现接口
  • 线程池的核心参数和原理
      • 核心参数
      • 原理
  • 为什么是先添加队列 队列满了在创建最大线程?

在 Java 中,线程的生命周期包括几个不同的状态,这些状态可以由线程的状态机(State Machine)来表示。线程状态的转换遵循一定的规则,并且可以通过 Java 线程 API 来监控和控制。以下是 Java 线程的生命周期及其状态:

  1. 新建(New)状态
    • 当线程被创建时,它处于新建状态。在这个状态下,线程还没有开始执行。
    • 可以通过 start() 方法将线程从新建状态转换为就绪状态。
  2. 就绪(Runnable)状态
    • 线程调用 start() 方法后,它进入就绪状态。在这个状态下,线程已经准备好执行,但是它还不能立即执行,因为它需要等待操作系统分配CPU时间。
    • 线程从就绪状态转换为运行状态,需要依赖于操作系统的调度器。
  3. 运行(Running)状态
    • 线程获得CPU时间后,进入运行状态。在这个状态下,线程正在执行。
    • 如果线程正在执行,但是由于某些原因(如等待IO操作完成)而暂时无法继续执行,它将转换为阻塞状态。
  4. 阻塞(Blocked)状态
    • 线程由于等待外部资源(如等待同步锁、等待IO操作完成等)而无法继续执行时,它进入阻塞状态。
    • 阻塞状态的线程不会占用CPU时间。当等待的资源可用时,线程将转换为就绪状态。
  5. 等待(Waiting)状态
    • 线程执行 Object.wait() 方法后,进入等待状态。在这个状态下,线程不会被分配CPU时间,并且不会被操作系统调度。
    • 线程从等待状态转换为就绪状态,需要等待其他线程调用 Object.notify()Object.notifyAll() 方法。
  6. 计时等待(Timed Waiting)状态
    • 线程执行 Thread.sleep()Object.wait(long timeout) 方法后,进入计时等待状态。
    • 与等待状态类似,计时等待状态的线程不会被分配CPU时间,并且不会被操作系统调度。
    • 线程从计时等待状态转换为就绪状态,有两种情况:一种是等待时间到期,另一种是其他线程调用 Thread.interrupt() 方法。
  7. 终止(Terminated)状态
    • 线程执行完毕后,进入终止状态。在这个状态下,线程不再运行。
    • 一旦线程进入终止状态,它就不能再被启动或恢复。
      Java 线程的状态转换遵循一定的规则,并且可以通过 Java 线程 API 来监控和控制。了解线程的生命周期和状态对于编写多线程应用程序非常重要。

java如何创建线程

在 Java 中,有多种方式可以创建线程,包括继承 Thread 类和使用 Runnable 接口。以下是这两种方法的基本步骤:

继承 Thread

  1. 创建一个新类,继承自 Thread
  2. 重写 run() 方法,在这个方法中编写线程要执行的代码。
  3. 创建新类的对象
  4. 调用 start() 方法,启动线程。
class MyThread extends Thread {public void run() {// 线程要执行的代码System.out.println("Thread is running.");}
}
public class Main {public static void main(String[] args) {MyThread thread = new MyThread();thread.start(); // 启动线程}
}

使用 Runnable 接口

  1. 创建一个新类,实现 Runnable 接口
  2. 实现 run() 方法,在这个方法中编写线程要执行的代码。
  3. 创建新类的对象
  4. 创建 Thread 类的对象,并将步骤2中创建的对象作为参数传递给 Thread 类的构造函数。
  5. 调用 start() 方法,启动线程。
class MyRunnable implements Runnable {public void run() {// 线程要执行的代码System.out.println("Thread is running.");}
}
public class Main {public static void main(String[] args) {MyRunnable runnable = new MyRunnable();Thread thread = new Thread(runnable);thread.start(); // 启动线程}
}

选择继承还是实现接口

  • 继承 Thread 类:这种方式相对简单,但是因为 Java 不支持多重继承,所以如果类已经继承自其他类,就不能再继承 Thread 类。
  • 实现 Runnable 接口:这种方式更灵活,因为一个类可以实现多个接口。
    在实际应用中,推荐使用实现 Runnable 接口的方式,因为它更符合 Java 的设计哲学,即单一继承原则。

线程池的核心参数和原理

线程池的核心参数和原理涉及线程池的配置和管理,以及它如何有效地处理并发任务。以下是线程池的一些核心参数和原理:

核心参数

  1. 核心线程数(Core Pool Size)
    • 核心线程数是指线程池中始终存在的线程数量,即使这些线程处于空闲状态。
    • 即使没有新的任务提交,核心线程数也不会减少。
  2. 最大线程数(Maximum Pool Size)
    • 最大线程数是指线程池能够创建的最大线程数量。
    • 当线程池中的线程数达到最大值时,新提交的任务会被加入到队列中等待执行。
  3. 队列容量(Queue Capacity)
    • 队列容量是指线程池中的任务队列可以存储的任务数量。
    • 当队列已满时,如果核心线程数未达到上限,线程池会创建新的线程来处理任务;如果核心线程数已达到上限,线程池会拒绝新的任务,并抛出 RejectedExecutionException
  4. 存活时间(Keep-Alive Time)
    • 存活时间是指当线程池中的线程数超过核心线程数时,多余的空闲线程将在多长时间后被终止。
    • 存活时间可以通过 keepAliveTimeTimeUnit 参数指定。
  5. 时间单位(Time Unit)
    • 时间单位参数用于指定存活时间的时间单位,例如 TimeUnit.SECONDSTimeUnit.MILLISECONDS 等。

原理

  1. 任务提交
    • 当有新任务提交时,线程池会检查当前线程数是否小于核心线程数。
    • 如果小于,则创建新的线程来执行任务。
    • 如果等于或大于核心线程数,则将任务加入到任务队列中。
  2. 任务执行
    • 如果任务队列未满,新任务会被加入到队列中。
    • 如果任务队列已满,线程池会创建新的线程来执行任务,直到线程数达到最大线程数。
  3. 空闲线程处理
    • 当线程池中的线程数超过核心线程数时,多余的空闲线程会在存活时间内被终止。
    • 存活时间可以通过 keepAliveTimeTimeUnit 参数指定。
  4. 任务执行完成后
    • 执行完任务的线程会重新进入空闲状态,等待新的任务。
    • 如果存活时间到期,空闲线程将被终止。
  5. 任务拒绝
    • 当任务队列已满,且线程数达到最大线程数时,新的任务会被拒绝,并抛出 RejectedExecutionException
      线程池的核心原理是通过控制线程数和任务队列的大小,以及管理空闲线程的生命周期,来实现对并发任务的高效处理。通过合理配置线程池的参数,可以有效地平衡系统资源的使用和任务的处理效率。

为什么是先添加队列 队列满了在创建最大线程?

线程池的工作流程设计是先添加任务到队列,当队列满了之后再创建新的线程,这是为了在并发场景下尽可能地提高系统的性能和资源利用率。这种设计理念基于以下几个原因:

  1. 减少线程创建和销毁的开销
    • 创建和销毁线程是有成本的,因为涉及到内存分配、线程上下文切换等操作。
    • 如果每次有新任务到来时都立即创建新线程,那么在任务量较小的情况下,线程创建和销毁的开销可能会超过实际执行任务的收益。
  2. 提高系统资源的利用率
    • 在任务量不大的情况下,线程池中的线程可能大部分时间都在等待任务。
    • 如果任务队列满了,那么新任务的到来可以唤醒等待中的线程,而不是创建新的线程。这样可以提高CPU和其他系统资源的利用率。
  3. 避免线程数过多
    • 如果每次有新任务到来时都创建新线程,可能会导致线程数过多,进而导致系统资源不足,如内存溢出。
    • 通过先添加任务到队列,可以限制线程数的增长,从而避免资源过度消耗。
  4. 线程池的动态调整
    • 线程池可以根据任务量和系统负载动态调整线程数。
    • 当任务量增加时,线程池会创建新的线程来处理任务;当任务量减少时,空闲线程会在存活时间内被终止,从而减少线程数。
  5. 避免频繁的线程创建和销毁
    • 频繁的线程创建和销毁会导致系统性能下降,因为线程上下文切换的开销较大。
    • 通过使用任务队列作为缓冲区,可以减少这种开销,让线程有更多的时间来执行任务。
      因此,线程池的设计理念是先使用任务队列作为缓冲,以减少线程创建和销毁的开销,并提高系统资源的利用率。当任务队列满了之后,再创建新的线程来处理任务,这样可以更好地平衡系统的性能和资源利用率。

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

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

相关文章

深入Netty RPC内核:编码、通信与性能优化全指南

1.Netty 简介 1.1. Netty的优势 Netty是一个异步的、事件驱动的网络应用框架,用于快速开发高性能、高可靠性的服务器和客户端程序。它提供了丰富的缓冲区类型和传输抽象,可以让您轻松地进行直接内存操作,减少拷贝和内存消耗。 1.2. Netty在…

学习小记录——python函数的定义和调用

今日小好运,未来有好运。🎁💖🫔 分享个人学习的小小心意,一起来看看吧 函数的定义 函数通常来说就是带名字的代码块,用于完成具体的工作,需要使用的时候调用即可,这不仅提高代码的…

[数据集][目标检测]旋风检测数据集VOC+YOLO格式157张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):159 标注数量(xml文件个数):159 标注数量(txt文件个数):159 标注类别…

音频信号分析与实践

音频信号分析与实践课程,方便理解音频信号原理和过程 1.音频信号采集与播放 两种采样模式和标准的采样流程 人说话的声音一般在2kHz一下: 采样频率的影响:采样率要大于等于信号特征频率的2倍;一般保证信号完整,需要使用10倍以上的…

『大模型笔记』FlashAttention技术细节介绍!

FlashAttention技术细节介绍! 文章目录 一. FlashAttention技术介绍1. 什么是闪存注意力(FlashAttention)?1.1 自注意力在序列长度方面是平方级的1.2 在现代GPU中,计算速度实际上已经超过了内存速度,因此瓶颈实际上是内存速度而不是计算速度1.3 闪存注意力是一种面向IO的精…

unity2020打包webGL时卡进程问题

我使用的2020.3.0f1c1,打包发布WEB版的时候会一直卡到asm2wasm.exe这个进程里,而且CPU占用率90%以上。 即使是打包一个新建项目的空场景也是同样的问题,我尝试过一直卡在这里会如何,结果还真打包成功了。只是打包一个空场景需要20…

..\MYLIB\modbus.c(49): error: #84: invalid combination of type specifiers

在keil中添加相应的文件出现以下问题时 ..\MYLIB\modbus.c(49): error: #84: invalid combination of type specifiers 是由于:在定义的函数体的前面有一个变量类型

Ubuntu 安装 Vulkan SDK

LunarG VulkanSDK Packages 此存储库包含Ubuntu 20.04和22.04的最新SDK版本。 This repository contains the most recent SDK releases for Ubuntu 20.04 and 22.04. 有关LunarG Vulkan SDK的更多信息,请访问文档部分。 For more information about the LunarG V…

java web 前端开发:深入剖析与实战指南

java web 前端开发:深入剖析与实战指南 在当今数字化时代,Java Web前端开发已经成为了构建优秀用户体验的关键环节。它涉及到多个方面,包括界面设计、交互逻辑、性能优化等。本文将从四个方面、五个方面、六个方面和七个方面,对J…

iOS怎么Python?深度探索iOS平台上的Python之路

iOS怎么Python?深度探索iOS平台上的Python之路 在移动开发的广袤领域中,iOS以其独特的生态系统和严格的审核机制而闻名。然而,对于希望在iOS平台上使用Python进行开发的开发者来说,这似乎是一个颇具挑战的任务。那么,…

2024年西安交通大学程序设计竞赛校赛

2024年西安交通大学程序设计竞赛校赛 文章目录 2024年西安交通大学程序设计竞赛校赛D瑟莉姆的宴会E: 雪中楼I: 命令行(待补)J:最后一块石头的重量(待补)K: 崩坏:星穹铁道(待补)M:生命游戏N: 圣诞树 D瑟莉姆的宴会 解题思路: ​ …

模拟建造游戏:城市:天际线Cities: Skylines for Mac/win中文原生版

《城市:天际线》(Cities: Skylines)是一款由Colossal Order开发,Paradox Interactive发行的城市建设模拟游戏。这款游戏于2015年首次发布,迅速赢得了玩家和评论家的好评,并成为了备受欢迎的城市建设游戏之一…

java代码审计之fastjson反序列化漏洞

fastjson反序列化漏洞分析 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。该产品主要提供了两个接口&…

2024.6.1每日一题

儿童节快乐😄 LeetCode 给小朋友们分糖果 I 题目链接:2928. 给小朋友们分糖果 I - 力扣(LeetCode) 题目描述 给你两个正整数 n 和 limit 。 请你将 n 颗糖果分给 3 位小朋友,确保没有任何小朋友得到超过 limit 颗…

STM32作业实现(六)闪存保存数据

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

一些通用指令和网站

1、因为很多库是国外的,在国内下载可能不成功或者网速很慢,这是可以用国内镜像网站下载 永久的修改镜像源地址:pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 2、色卡查询网: 网页常用色彩 网页配…

Mistral大模型:Getting Started With Mistral

Getting Started With Mistral 本文是学习 https://www.deeplearning.ai/short-courses/getting-started-with-mistral/ 这门课的学习笔记。 What you’ll learn in this course In this course, you’ll access Mistral AI’s collection of open source and commercial mod…

物联网实战--平台篇之(十二)设备管理前端

目录 一、界面演示 二、设备列表 三、抖动单元格 四、设备模型 五、设备编辑 本项目的交流QQ群:701889554 物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html 物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631333.htm…

Java利用POI绘制表格

前提需求 最近公司要求写一些记录的表格,并且带有导出功能。再深入学习后,表格的底层其实就是list遍历塞值,导出功能的话可以由前端,后端实现,但技多不压身嘛,这里我自己就写了后端的导出功能,…

day-37 电话号码的字母组合

思路 设置一个char型的二维数组,每次从号码对应的子母中选出一个,拼接在一起即可 解题方法 注意:有的数字对应三个字母,有的对应四个字母 Code class Solution {public char arr[][]{{a,b,c, },{d,e,f, },{g,h,i, },{j,k,l, },…