线程池总结

线程池的执行流程总结:

从创建线程池的参数分析:

1.提交新线程,线程池会在线程池中分配一个空闲线程,用于执行线程任务。

2.参数(int corePoolSize):核心线程数

  • 如果线程池中不存在空闲线程,则线程池会判断当前“存活的线程数”是否小于核心线程数
  • 如果小于核心线程数,线程池会创建一个新线程(核心线程)去处理新线程任务。

3.参数(BlockingQueue<Runnable> workQueue):工作队列

        如果大于核心线程数,线程池会检查工作队列(workQueue),如果工作队列未满,则将该线程任务放入工作队列进行等待。线程池中如果出现空闲线程,将从工作队列中按照FIFO的规则取出1个线程任务并分配执行。

4.参数(int maximumPoolSize):最大线程数

 如果工作队列已满,则判断线程数是否达到最大线程数maximumPoolSize.

  • 如果当前“存活线程数”没有达到最大线程数maximumPoolSize,则创建一个新线程(非核心线程)执行新线程任务。
  • 如果当前“存活线程数”已经达到最大线程数maximumPoolSize,直接采用拒绝策略处理新线程任务。

线程池的状态:

线程池的状态分为:RUNNINGSHUTDOWNSTOPTIDYINGTERMINATED

RUNNING:运行状态,线程池一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0.该状态的线程池会接收新任务,并处理工作队列中的任务。

  • 调用线程池的shutdown()方法,可以切换到SHUTDOWN关闭状态
  • 调用线程池的shutdownNow()方法,可以切换到STOP停止状态

SHUTDOWN:关闭状态,该状态的线程池不会接收新任务,但会处理工作队列中的任务;

  • 当工作队列为空时,并且线程池中执行的任务也为空时,线程池进入 TIDYING状态。

STOP:停止状态,该状态下的线程不会接收新任务,也不会处理阻塞队列中的任务,而且会中断正在进行中的任务。

当线程池中的任务为空时,进入TIDYING状态;

TIDYING:整理状态,该状态表明所有的任务已经运行终止,记录的任务数量为0;

  • terminated()执行完毕,进入TERMINATED状态;

TERMINATED:终止状态,该状态表示线程池彻底关闭。

线程池的类型:

FixedThreadPool

线程数固定的线程池,使用Executors.newFixedThreadPool()创建

线程池参数:

  • 核心线程数和最大线程数一致
  • 非核心线程线程空闲存活时间,即keepAliveTime为0
  • 阻塞队列为无界队列LinkedBlockingQueue
public class Test05 {public static void main(String[] args) {//创建一个固定大小的线程池ExecutorService executorService = Executors.newFixedThreadPool(4);for(int i=0;i<6;i++) {executorService.execute(new Task("线程"+i));}//关闭线程池executorService.shutdown();}
}
class Task implements Runnable{private String taskName;public Task(String taskName) {this.taskName=taskName;}@Overridepublic void run() {System.out.println("启动线程==>"+this.taskName);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("结束线程<="+this.taskName);}	
}

运行结果为:
启动线程==>线程0
启动线程==>线程3
启动线程==>线程2
启动线程==>线程1
结束线程<=线程2
结束线程<=线程1
结束线程<=线程0
结束线程<=线程3
启动线程==>线程5
启动线程==>线程4
结束线程<=线程4
结束线程<=线程5

执行分析:一次性放入6个线程,由于线程池只有固定的4个线程,因此,前4 个任务会同时执行,等到有空闲线程后,才会执行后面的两个任务。  

工作机制:
a、提交线程任务

b、如果线程数少于核心线程数,创建核心线程执行任务

c、如果线程数等于核心线程数,把任务添加到LinkedBlockingQueue阻塞队列

d、如果线程执行完任务,去阻塞队列领取任务,继续执行

使用场景:适用于处理CPU密集型任务,确保CPU在长期被工作线程使用的情况下,尽可能少的分配线程,即适用执行长期的任务。

CachedThreadPool

可缓存线程池,线程数根据任务动态调整的线程池,使用Executors.newCacheThreadPool()创建

线程池参数:

  • 核心线程数为0
  • 最大核心线程数为Integer.MAX_VALUE
  • 工作队列是SynchronousQueue同步队列
  • 非核心线程空闲存活是时间为60秒

 将线程池改为CachedThreadPool

ExecutorService executorService = Executors.newCachedThreadPool();

执行结果:

启动线程==>线程1
启动线程==>线程3
启动线程==>线程2
启动线程==>线程0
启动线程==>线程4
启动线程==>线程5
结束线程<=线程0
结束线程<=线程3
结束线程<=线程5
结束线程<=线程2
结束线程<=线程1
结束线程<=线程4

执行分析:由于这个线程池的实现会根据任务数量动态调整线程池的大小,所以6个任务可一次性全部同时执行。  

工作机制:

a、提交线程任务

b、因为核心线程数为0,所有任务直接添加到SynchronousQueue工作队列

c、判断是否有空闲线程,如果有,就去取出任务执行

d、如果没有空闲线程,就创建一个新线程

e、执行完任务的线程,还可以存活60秒,如果在这期间,接到任务,可以继续存活下去;否则,被销毁。

使用场景:用于并发执行大量短期的小任务。

SingleThreadExecutor

单线程化的线程池,使用Executors.newSingleThreadExecutor()创建

线程池参数:

  • 核心线程数为1
  • 最大线程数也为1
  • 阻塞队列是LinkedBlockingQueue
  • 非核心线程数空闲存活时间为0秒

 将线程池改为SingleThreadExecutor

ExecutorService executorService = Executors.newSingleThreadExecutor();

执行结果:

启动线程==>线程0
结束线程<=线程0
启动线程==>线程1
结束线程<=线程1
启动线程==>线程2
结束线程<=线程2
启动线程==>线程3
结束线程<=线程3
启动线程==>线程4
结束线程<=线程4
启动线程==>线程5
结束线程<=线程5 

执行结果分析: 一次只执行一个线程,当该线程彻底执行完毕,再执行下一个线程。

使用场景:适用于串行执行任务的场景,将任务按顺序执行。

ScheduleThreadPool

能实现定时、周期性任务的线程池,,使用Executors.newScheduledThreadPool()创建

线程池参数:

  • 最大线程数为Integer.MAX_VALUE
  • 阻塞队列是DelayedWorkQueue
  • keepAliveTime为0

 将线程池改为ScheduledThreadPool 

ExecutorService executorService = Executors.newScheduledThreadPool(3);

延迟3秒钟后,任务只执行1次

executorService.schedule(new Task("线程A"),3,TimeUnit.SECONDS);

 延迟2秒钟后,每隔3秒执行一次

executorService.scheduleAtFixedRate(new Task("线程A"), 2, 3, TimeUnit.SECONDS);
executorService.scheduleWithFixedDelay(new Task("线程A"), 2, 3, TimeUnit.SECONDS);

FixedRate和Fixedelay的区别:

  •  FixedRate是指任务总是以固定时间间隔触发,不管任务执行多长时间;
  • Fixedelay是指,上一次任务执行完毕后,等待固定的时间间隔,再执行下一次的任务;

使用场景:周期性执行任务,并且需要限制线程数量的需求场景。

线程池的配置参数总结

1.核心线程数:corePoolSize

int corePoolSize

核心线程数也就是线程池的最小线程数量。

  • 核心线程会一直存活,不会被回收,除非设置了核心线程超时时间;
  • 在创建线程池后,默认情况下,线程池中没有任何线程,调用excute()方法添加一个任务。

当线程池中没有空闲线程时,查看是否超过核心线程数:

  • 线程数量小于核心线程数,则马上创建新的核心线程来执行线程任务。
  • 线程数量大于核心线程数,则查看工作队列是否超出。

CPU密集型和IO密集型的区别:

(1)CPU密集型

CPU密集型也叫计算密集型,指的是系统的硬盘、内存性能相对CPU要好很多,此时,系统运作大部分的状况是CPU Loading 100%,CPU要读/写I/O(硬盘/内存),I/O在很短的时间就可以完成,而CPU还有许多运算要处理,CPU Loading 很高。

在多重程序系统中,大部分时间用来做计算、逻辑判断等CPU动作的程序称之CPU bound。例如一个计算圆周率至小数点一千位以下的程序,在执行的过程当中绝大部分时间用在三角函数和开根号的计算,便是属于CPU bound的程序

CPU bound的程序一般而言CPU占用率相当高。这可能是因为任务本身不太需要访问I/O设备,也可能是因为程序是多线程实现因此屏蔽掉了等待I/O的时间。

(2)IO密集型

IO密集型指的是系统的CPU性能相对硬盘、内存要好很多,此时,系统运作,大部分的状况是CPU在等I/O (硬盘/内存) 的读/写操作,此时CPU Loading并不高。

I/O bound的程序一般在达到性能极限时,CPU占用率仍然较低。这可能是因为任务本身需要大量I/O操作,而pipeline做得不是很好,没有充分利用处理器能力。

(3)先看下机器的CPU核数,然后在设定具体参数:

自己测一下自己机器的核数

System.out.printlnRuntime.getRuntime().availableProcessors());

即CPU核数 = Runtime.getRuntime().availableProcessors()

(4)分析下线程池处理的程序是CPU密集型还是IO密集型

CPU密集型:corePoolSize = CPU核数 + 1

IO密集型:corePoolSize = CPU核数 * 2

2.最大线程数:maximumPoolSize

int maximumPoolSize

是指线程池中允许的最大线程数量。

当工作队列已满,且存活线程数超过了核心线程数时,线程池判断存活线程数是否超过最大线程数:

  • 未超过最大线程数:创建新线程来执行该任务。
  • 超过最大线程数:执行拒绝策略。
3.非核心的空闲线程的存活时间:keepAliveTime

long keepAliveTime

当线程数大于核心线程数时,空闲的线程等待新任务到达的最大时间,如果超过这个时间线程还没有需要执行的任务,该空闲线程就会销毁。

4.keepAliveTime的单位:unit

TimeUnit unit

keepAliveTime的单位,枚举类型的TimeUnit类。

5.阻塞工作队列:workQueue

BlockingQueue<Runnable> workQueue

在任务执行之前,用来存储任务的工作队列,此队列只保存由excute()方法提交的Runnable类型的任务。

当存活的线程数大于核心线程数,查看工作队列:

  • 工作队列未满:将新的请求任务加入工作队列;
  • 工作队列已满:线程池判断是否超过最大线程数。

5.1 ArrayBlockingQueue

基于数组有界阻塞队列,FIFO(先进先出)。

 

  • capacity:队列初始化大小
  • fair:表示该队列中的可重入锁是否公平,默认为false

当线程池中已经存在最大数量的线程时候,再请求新的任务,这时就会将任务加入工作队列的队尾,一旦有空闲线程,就会取出队头执行任务。

5.2 LinkedBlockingQueue

基于链表的误解阻塞队列,默认最大容量为Integer.MAX_VALUE,可认为是无限队列,FIFO(先进先出)。

指定工作队列大小,则最大线程数量的限制是有效的。

5.3 SynchronousQueue

可以将SynchronousQueue看作是一个没有容量的阻塞队列,它严格遵循FIFO(先进先出)的原则,但特殊的是,它不会保存任何元素,而是直接在不同的线程间进行传递。

6.线程工厂:threadFactory

ThreadFactory threadFactory

用于创建一个新线程时使用的工厂,可以用来设置线程名。

没有特别声明时,使用Executors工具类提供的默认线程工厂Executors.defaultThreadFactory()

自定义线程工厂时,要实现ThreadFactory接口,重写newThread()方法。

7.拒绝策略:handler

RejectedExecutionHandler handler

当线程池内的线程被耗尽,并且工作队列已满,对于新提交的任务,将使用拒绝策略进行处理。

7.1 AbortPolicy:丢弃线程任务,并抛出异常 

没有特别声明时,使用默认的拒绝策略defaultHandler

 7.2 DiscardOldestPolicy:将工作队列的对头移除,线程池重新执行该线程任务

7.3 DiscardPolicy:直接丢弃该任务

7.4 CallerRunPolicy:线程池没有关闭时,线程自己调用run方法

7.5 自定义的拒绝策略:实现RejectedExecutionHandler接口

重写void rejectedExecution(Runnable r, ThreadPoolExecutor executor)方法

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

ADB 安装教程:如何在 Windows、macOS 和 Linux 上安装 Android Debug Bridge

目录 一、ADB 介绍 二、Windows 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 验证 ADB 安装 4. 配置环境变量 5. 验证全局 ADB 使用 三、macOS 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 配置环境变量 4. 验证 ADB 安装 四、Linux 系统安装 ADB 1. 使用包管理器安装…

【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第二篇-着色器制作】

在上一篇文章中&#xff0c;我们已经理顺了实现流程。 接下来&#xff0c;我们将在UE5中&#xff0c;从头开始一步一步地构建一次流程。 通过这种方法&#xff0c;我们可以借助一个熟悉的开发环境&#xff0c;使那些对着色器不太熟悉的朋友们更好地理解着色器的工作原理。 这篇…

MySQL 主从复制部署与优化

文章目录 前言 在现代数据库管理中&#xff0c;MySQL 主从复制是一种关键技术&#xff0c;用于提高数据的可用性和性能。随着 Docker 容器技术的普及&#xff0c;利用 Docker 搭建 MySQL 主从复制环境已成为一种趋势&#xff0c;它提供了一种简便、高效且可扩展的解决方案。本…

LED 生产电子看板实现工厂精准管理

在当今竞争激烈的制造业领域&#xff0c;工厂的管理效率和精度直接关系到企业的生存与发展。而 LED 生产电子看板的出现&#xff0c;为工厂实现精准管理带来了全新的解决方案。 一、电子看板能够实现对生产进度的精准把控 在传统的工厂管理中&#xff0c;生产进度的了解往往依…

协同编程的艺术:SIDE 让团队协作更上一层楼

一、协同编程的现状 在当前软件开发中&#xff0c;团队协作面临着诸多挑战。沟通不畅常常导致项目进度延迟&#xff0c;版本控制复杂使得代码合并困难重重。传统 IDE 在协同工作方面存在明显的局限性&#xff0c;缺乏实时协作功能&#xff0c;团队成员之间的沟通工具也不够完善…

个人小结(2.0)

离谱&#xff0c;困扰着几周的问题今天偶然发现了解决方法。 问题如下&#xff1a;就是对应的模块引入爆红&#xff0c;但是单击进入引入的文件没有问题 然后它的提示是&#xff1a; 无法找到模块“../views/screen/index.vue”的声明文件。“c:/Users/10834/Desktop/0716_pro…

班主任群发成绩教程,宝藏工具来减负

今天想和大家聊聊班主任的那些事儿。当班主任可真不是一件轻松的工作啊。要备课吧&#xff0c;得精心设计每一个教学环节&#xff0c;从教学目标到教学方法&#xff0c;从课程导入到课后作业&#xff0c;每个细节都得考虑周全。 还要管理班级纪律&#xff0c;处理同学之间的小摩…

2024年NAS个人存储完美方案(最牛方案不服来战)

成果展示 背面展示 正面展示 为什么需要nas 速度优势:使用公共云盘,速度完全依赖公网传输速度。比如家庭300Mbps宽带,使用百度网盘SVip,上传2.5MB/s,下载30MB/s。而使用家用nas,速度完全取决路由器内网性能,基本上达到千兆或2.5GE。内容优势:向公共云盘上传的文件全…

miniQMT量化软件好用吗?miniQMT策略编辑流程步骤详细解答!

miniQMT的策略编辑流程步骤主要包括以下几个方面&#xff1a; 一、准备工作 配置Python环境&#xff1a; 下载并安装Python环境&#xff0c;确保版本兼容。 下载迅投官方提供的xtquant包&#xff0c;并配置到Python的site-packages路径下&#xff0c;以便在Python环境中引入…

如何在Spring Boot中无缝集成LangChain4j,玩转AI大模型!

0 前言 LangChain4j 提供了用于以下功能的 Spring Boot 启动器&#xff1a; 常用集成声明式 AI 服务 1 常用集成的 Spring Boot starters Spring Boot 启动器帮助通过属性创建和配置 语言模型、嵌入模型、嵌入存储 和其他核心 LangChain4j 组件。 要使用 Spring Boot 启动…

mybatisplus中id生成策略

使用Tableld(value,type) 1.typeIdType.AUTO自增主键 2.typeIdType.ASSIGN,雪花算法生成 mybatisplus id生成策略全局配置 配置表前缀以及id生成策略 mybatis-plus:global-config:db-config:id-type: autotable-prefix: :t_

OpenAi assistant run always fails when called from PHP

题意&#xff1a;从 PHP 调用时&#xff0c;OpenAI 助理运行总是失败。 问题背景&#xff1a; The runs I create with the openai-php library fail direct in 100% of cases. What am I doing wrong? I do not have much experience with php but this is the test script.…

VS2019配置C++版本的GDAL

VS2019配置GDAL教程 【特别注意】 vs2019编译好的GDAL库是可以在VS2022上面使用的&#xff0c;我这边做项目已经测试过没有问题&#xff0c;所以vs2022使用vs2019编译的gdal没有问题。 【编译版本介绍】 由于GDAL在vs2019源码流程有点复杂&#xff0c;因此我们在这不做讲解…

【Git必看系列】—— 2024年前后端开发必须要知道的GitFlow工作流

自从 Linux 之父Linus Torvalds对当时的版本控制工具感到不满&#xff0c;亲自动手创造了 Git 以来&#xff0c;Git 已经逐渐在版本控制领域占据了主导地位。不论你的代码仓库托管在 GitHub 还是 GitLab&#xff0c;不论你用的是 SourceTree、GitKraken 这样的图形界面&#xf…

华为 HCIP-Datacom H12-821 题库 (25)

&#x1f423;博客最下方微信公众号回复题库,领取题库和教学资源 &#x1f424;诚挚欢迎IT交流有兴趣的公众号回复交流群 &#x1f998;公众号会持续更新网络小知识&#x1f63c; 1.以下哪些事件会导致 IS-IS 产生一个新的 LSP? A、邻接 Up 或Down B、引入的 IP 路由发送变…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)2.1-2.2

目录 第四门课 卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;第二周 深度卷积网络&#xff1a;实例探究&#xff08;Deep convolutional models: case studies&#xff09;2.1 为什么要进行实例探究&#xff1f;&#xff08;Why look at case studies?&…

PyTorch深度学习快速入门教程【土堆】基础知识篇

Juptyer 版本&#xff1a; Python 3.9.19Pytorch 2.4.1 (pytorch0) C:\Users\25694>conda install nb_conda_kernels(pytorch0) C:\Users\25694>jupyter notebook使用conda环境的pytorch&#xff1a; 成功解决python.exe无法找到程序入口 无法定位程序输入点 shifte…

【Python语言初识(一)】

一、python简史 1.1、python的历史 1989年圣诞节&#xff1a;Guido von Rossum开始写Python语言的编译器。1991年2月&#xff1a;第一个Python编译器&#xff08;同时也是解释器&#xff09;诞生&#xff0c;它是用C语言实现的&#xff08;后面&#xff09;&#xff0c;可以调…

茶思屋直播|TinyEngine+AI:聚焦主航道,在实践中探索低代码技术黑土地

低代码引擎使能开发者定制低代码平台。它是低代码平台的底座&#xff0c;提供可视化搭建页面等基础能力&#xff0c;既可以通过线上搭配组合&#xff0c;也可以通过cli创建个人工程进行二次开发&#xff0c;实时定制出自己的低代码平台。适用于多场景的低代码平台开发&#xff…

【C++ 学习】多态的基础和原理(10)

目录 前言1. 概念2. 多态的定义及实现2.1 多态的构成条件2.2 虚函数2.3 虚函数重写2.4 虚函数重写的例外2.4.1 协变2.4.1 析构函数的重写 2.5 多态调用和普通调用2.6 函数重写/函数隐藏/函数重载 的对比2.6.1 函数重写2.6.2 函数隐藏2.6.3 函数重载 2.7 C11 final 和override 3…