并发编程——4.线程池
这篇文章我们来讲一下线程池的相关内容
目录
1.什么是线程池
1.1为什么要用线程池
1.2线程池的优势
2.线程池的使用
3.线程池的关闭
4.线程池中的execute和submit方法的一些区别
5.线程池的参数和原理
6.自定义线程池
7.总结
1.什么是线程池
1.1为什么要用线程池
首先,我们要清楚这样的一个问题,我们为什么要用线程池?
思考下面的这样的一个场景:某线上商城做秒杀活动,1秒内有10万个请求打来,我们的服务器能在1秒内创建10万个线程吗?显然是不合理的。其次,我们使用线程时会伴随着线程的创建和消耗,当线程数量很多时,这会占用机器的资源,所以这也不合理。为了解决上面提到的问题,所以我们使用了线程池。
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?在Java中可以通过线程池来达到这样的效果。
线程池:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
1.2线程池的优势
线程池做的工作主要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行。
它的主要特点为:线程复用;控制最大并发数;管理线程。
线程池的优势:
- 第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的销耗。
- 第二:提高响应速度。当任务到达时,任务可以不需要等待线程创建就能立即执行。
- 第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会销耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控
2.线程池的使用
对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在java.util.concurrent . Executors 线程工厂类里面提供了一些静态工厂,生成一些常用的线程池。官方建议使用 Executors工程类来创建线程池对象。Java类库提供了许多静态方法来创建一个线程池:
Executors类中创建线程池的方法如下:
- a、newFixedThreadPool创建一个固定长度的线程池,当到达线程最大数量时,线程池的规模将不再变化。
- b、newCachedThreadPool创建一个可缓存的线程池,如果当前线程池的规模超出了处理需求,将回收空的线程;当需求增加时,会增加线程数量;线程池规模无限制。
- c、newSingleThreadPoolExecutor创建一个单线程的Executor,确保任务对了,串行执行
- d、newScheduledThreadPool创建一个固定长度的线程池,但是是可以定时的进行调度
下面我们就通过代码来看一下各种方法的使用
这个其实没啥好说的,因为这个用的是Java中提供的线程池的工具类,是很简单的,直接用就行。
3.线程池的关闭
下面看一下线程池的关闭
我们创建一个线程池,在使用完毕后,一定要关闭线程池,关闭线程池的代码要放在finally里面,目的是为了避免程序出错,导致线程池没有关闭。我们关闭线程池后,线程池中正在执行的线程不会立刻被停止,它会等到该线程执行完毕后再关闭,即线程池是会等待线程池中所有的线程都被执行完才关闭。
为什么要关闭线程池?为了避免线程池中的线程一直占用系统资源,造成内存泄漏
下面看一下代码:
注意区分shutdown和shutdownNow二者的区别!
4.线程池中的execute和submit方法的一些区别
下面,我们来看一下线程池中的execute方法和submit方法的区别
区别一:
execute方法的入参只能是Runnable,而submit方法的入参可以是Runnable,也可以是Callable
下面看一下代码:
区别二:
execute的返回值为void类型,而submit的返回值为Future类型
下面看一下代码:
区别三:
execute 会在子线程中抛出异常,但是主线程中捕捉不到。而submit是不会立刻抛出异常,它会将此异常暂时存起来,如果想要将该异常抛出,需要用Future对象接收submit的返回值,然后调用Future的get方法。
下面看一下代码:
5.线程池的参数和原理
下面,我们来看一下线程池的参数和原理
首先,我们看一下我们四种创建线程池的方式,然后Ctrl+单击,看一下它的源码:
我们会发现,这四种创建线程池的源码基本相同,都是返回了一个ThreadPoolExecutor对象,区别就在于里面的参数不一样。我们再单击看一下ThreadPoolExecutor的源码:
如上图所示,下面我们来介绍一下ThreadPoolExecutor中参数的意思
- corePoolSize:核心线程数量(这个不用过多解释)
- maximumPoolSize:最大线程数量(就是这个线程池最大能开辟的线程数量)
- KeepAliveTime:非核心线程的空闲状态的存活时间(就是如何该线程不是核心线程,并且它是空闲的,那么它的存活时间是多少,是long类型的数字)
- unit:非核心线程的空闲状态的存活时间的单位
- workQueue:工作队列(阻塞队列)
- threadFactory:线程工程(创建线程用的,就是一个接口,然后平时使用的就是创建默认线程)
- handler:拒绝策略(就是当我们的核心线程数,阻塞队列,最大线程数都满了的情况的下,还有线程来,那么就按照这个拒绝策略进行拒绝)
下面就整个流程进行一下梳理:
首先,我们进行提交任务,然后程序会判断你提交的任务数量是否大于你创建线程池的核心线程数量,如何不大于,OK,那么程序开始创建线程,执行任务;如果大于了核心线程数量,那么多余的任务进入阻塞队列里面进行等待,如果这时阻塞队列满了,那么程序会判断你创建线程池的最大线程数量是否满了,如果没满,那么程序根据最大线程数量来创建线程,执行任务,如果这时最大线程数量也满了,那么就执行拒绝策略,多余的任务就被拒绝了,不接受了。
这里对最大线程数量和非核心线程空闲状态存活时间进行一下场景解释:
假设现在有一个促销秒杀活动,比如双十一、618等。你的网站日常活跃用户只有5000万,所以你的程序的核心线程数设置为5000万,然后最大线程数设置为7000万,但是在活动促销的那两个小时,你的网站的活跃用户达到了1亿,那么你就不可能再把最大线程数设置为7000万了,而是设置为1亿,但是你只有那两个小时的用户活跃数是1亿,所以你不可能一直让那1亿个线程开着,所以你将非核心线程的空闲存活时间设置为2h,时间一过,如果该非核心线程是空闲状态,那么该线程就被销毁,这样就可以节约资源了。
下面看一下拒绝策略:
这个了解一下就可以了。
6.自定义线程池
上面我们学习了线程池的核心源码和其中的一些参数的含义,下面我们来书写一个自定义的线程池,然后我们再来具体的分析一下
代码如下:
然后,我们来看一下输出结果:
下面再用一张图来解释一下吧:
其实这是很好理解的
7.总结
这篇文章我们主要介绍了一下线程池的相关内容,包括什么是线程池,怎么创建或者说怎么使用线程池,线程池的注意点,线程池中两个方法的区别,以及如何自定义线程池(线程池的源码会在源码篇章中写),这部分是比较重要的内容,要掌握。
相关文章:

并发编程——4.线程池
这篇文章我们来讲一下线程池的相关内容 目录 1.什么是线程池 1.1为什么要用线程池 1.2线程池的优势 2.线程池的使用 3.线程池的关闭 4.线程池中的execute和submit方法的一些区别 5.线程池的参数和原理 6.自定义线程池 7.总结 1.什么是线程池 1.1为什么要用线程池 首…...

阿里云魔搭发起“ModelScope-Sora开源计划”,将为中国类Sora模型开发提供一站式工具链
在2024年3月23日的全球开发者先锋大会上,阿里云的魔搭社区宣布了一个新计划:“ModelScope-Sora开源计划”。这个计划旨在通过开源方式,帮助中国在Sora模型类型上做出更多创新。这个计划提供了一整套工具,包括处理数据的工具、多模…...

大模型与数据分析:探索Text-to-SQL
当今大模型如此火热,作为一名数据同学,持续在关注LLM是如何应用在数据分析中的,也关注到很多公司推出了AI数智助手的产品,比如火山引擎数智平台VeDI—AI助手、 Kyligence Copilot AI数智助理、ThoughtSpot等,通过接入人…...

Unity VisionOS开发流程
Unity开发环境 Unity Pro, Unity Enterprise and Unity Industry 国际版 Mac Unity Editor(Apple silicon) visionOS Build Support (experimental) 实验版 Unity 2022.3.11f1 NOTE: 国际版与国服版Pro账通用,需要激活Pro的许可证。官方模板v0.6.2,非Pro版本会打…...

聊聊k8s服务发现的优缺点
序 本文主要研究一下使用k8s服务发现的优缺点 spring cloud vs kubernetes 这里有张spring cloud与kubernetes的对比,如果将微服务部署到kubernetes上面,二者有不少功能是重复的,可否精简。 这里主要是讲述一下如果不使用独立的服务发现&am…...
Tomcat是如何处理并发请求的?
Tomcat处理请求流程: Tomcat是采用了扩展JDK线程池的方案 :先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处…...

H12-831_561
单选题561、如图所示,R1使用Loopback0接口(IP地址为10.0.1.1/32)与R2的物理接口(IP地址为10.0.12.2/24)建立EBGP邻居关系,以下描述中正确的是哪一项? A.无需在R1和R2的BGP进程下指定ebgp-max-hop B.在R2的BGP进程下配置peer 10.0.1.1 ebgp-max-hop 2,且…...

Java23种常见设计模式汇总
七大原则网站地址:设计模式7大原则+类图关系-CSDN博客 创建型设计模式:创建型设计模式合集-CSDN博客 七大结构型设计模式:7大结构型设计模式-CSDN博客 11种行为型设计模式: 11种行为型模式(上࿰…...

神经网络与深度学习(一)
线性回归 定义 利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法 要素 训练集(训练数据)输出数据拟合函数数据条目数 场景 预测价格(房屋、股票等)、预测住院时间&#…...

算法学习——LeetCode力扣图论篇2
算法学习——LeetCode力扣图论篇2 1020. 飞地的数量 1020. 飞地的数量 - 力扣(LeetCode) 描述 给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相…...

大数据设计为何要分层,行业常规设计会有几层数据
大数据设计通常采用分层结构的原因是为了提高数据管理的效率、降低系统复杂度、增强数据质量和可维护性。这种分层结构能够将数据按照不同的处理和应用需求进行分类和管理,从而更好地满足不同层次的数据处理和分析需求。行业常规设计中,数据通常按照以下…...

css3之2D转换transform
2D转换transform 一.移动(translate)(中间用,隔开)二.旋转(rotate)(有单位deg)1.概念2.注意点3.转换中心点(transform-origin)(中间用空格)4.一些例子(css三角和旋转) 三…...
pytest中文使用文档----6临时目录和文件
1. 相关的fixture 1.1. tmp_path1.2. tmp_path_factory1.3. tmpdir1.4. tmpdir_factory1.5. 区别 2. 默认的基本临时目录 1. 相关的fixture 1.1. tmp_path tmp_path是一个用例级别的fixture,其作用是返回一个唯一的临时目录对象(pathlib.Path…...

从0开始搭建基于VUE的前端项目
准备与版本 安装nodejs(v20.11.1)安装vue脚手架(vue/cli 5.0.8) ,参考(https://cli.vuejs.org/zh/)vue版本(2.7.16),vue2的最后一个版本 初始化项目 创建一个git项目(可以去gitee/github上创建ÿ…...

elementUI this.$msgbox msgBox自定义 样式自定义 富文本
看这个效果是不是很炫?突出重点提示内容,对于用户交互相当的棒! 下来说说具体实现: let self = this const h = self.$createElement; this.$msgbox({title: null,message: h("p", {style: "margin-top:10px"}, [h("i", {class: "el-i…...
Lua与Python区别
Lua和Python都是流行的编程语言,但它们在设计哲学、应用领域和性能特点上有所不同。以下是Lua和Python之间的对比: 1. **设计哲学**: - Lua被设计为一个轻量级的嵌入式脚本语言,重点在于简单性和效率。它有一个小巧的标准库,通…...

Python学习(二)
数据容器 数据容器根据特点的不同,如: 是否支持重复元素是否可以修改是否有序,等 分为5类,分别是: 列表(list)、元组(tuple)、字符串(str)、集…...

管理阿里云服务器ECS -- 网站选型和搭建
小云:我已经学会了如何登录云服务器ECS了,但是要如何搭建网站呢? 老王:目前有很多的个人网站系统软件,其中 WordPress 是使用非常广泛的一款,而且也可以把 WordPress 当作一个内容管理系统(CMS…...

WPF中继承ItemsControl子类控件数据模板获取选中属性
需求场景 列表类控件,如 ListBox、ListView、DataGrid等。显示的行数据中,部分内容依靠选中时触发控制,例如选中行时行记录复选,部分列内容控制显隐。 案例源码以ListView 为例。 Xaml 部分 <ListView ItemsSource"{Bi…...

Android卡顿掉帧问题分析之实战篇
本文将结合典型实战案例,分析常见的造成卡顿等性能问题的原因。从系统工程师的总体角度来看 ,造成卡顿等性能问题的原因总体上大致分为三个大类:一类是流程执行异常;二是系统负载异常;三是编译问题引起。 1 流程执行异…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...