Java实战中如何使用多线程(线程池)及其为什么使用?

这个话题在入行之前就想过很多次,很多8古文或者你搜索的结果都是告诉你什么提高高并发或者是一些很高大上的话,既没有案例也没有什么公式去证明,但是面试中总是被问到,也没有实战经历,所以面试时一问到多线程的东西就无从下手,接下来我就谈谈我的理解。

1.Java中为什么要使用多线程?

多线程:其实是在主线程中再开启一个线程去执行。

为什么要用呢?

先不谈什么高并发,这三个字太荒谬。从基本的作用开始说,其实就是对于一个请求内的耗时操作另外开启一个新的异步线程,不让耗时操作阻塞主线程,这样主线程直接跳过耗时操作去往下面执行,然后返回结果给前端,提高了响应速度。

上案例,这个我们先看一下没有使用多线程的正常请求?

Controller

Service

很简单的东西,我模拟testThread这个里面的东西是一个耗时操作,让它睡了10秒,也就是相当于一个耗时操作。正常请求的话前端肯定是得等10s以后才有响应,就会显示一直加载

正常打印结果

也就是内容是自上而下依次执行的。

上面案例全是靠主线程自己执行的,假如现在使用多线程,就是对于10s耗时的testThread这个操作开启一个异步线程去执行,会有什么效果?此处暂时只加上一个注解就表示这个方法使用了多线程,下面会介绍如何使用,此处先知道就是开启了异步线程。

再来看看响应结果及其速度,

结果表明,它会先打印主线程的东西,然后再打印开启的异步线程内的东西,并且呢可能大家以为主线程提前返回了,那个10s的耗时操作怎么办?结束了吗?其实并没有它只是在后台继续执行10s结束后打印的“66666666666666”,但是我们提前结束了请求响应给了前端。这样前端就不用等很长时间才能拿到结果对吧。别说10s,实际2s都太慢了,但是这个耗时操作一般是什么呢?例如发送邮件,读取文件,等等,也可能是公司的具体业务,并且这个耗时操作的结果不影响你下面继续执行的代码,即你继续执行的代码不依赖于耗时操作的结果。

所以第一个用处就可总结为:开启异步线程处理耗时操作,提高请求的响应速度。

其次再谈谈下一个作用,充分利用资源,提高了CPU的利用率。什么意思呢?我们知道CPU在同一时间内是支持多个线程同时执行的,我们如果不使用多线程,也就是主线程自己去完成所有操作,一定会因为耗时操作阻塞主线程,此时导致CPU空闲,那利用率肯定不高嘛,那我们如果使用异步线程去做,那就是两个线程同时去完成一件事情,多多少少是要比一个线程要快的,而且我们充分利用了它的特性在同一时刻开启多个线程去执行。

所以第二个用户可总结为:分利用资源,提高了CPU的利用率

下面就说说提高高并发怎么回事?上面两个我一开始就知道而且比较好理解,但是高并发这个确实抽象,但是好在下点功夫还是能理解的。高并发:最多能同时处理的请求数量。我们知道那这个肯定是我们服务器的功能,拿我们后端Tomcat来说,支持最大线程数200,最大并发量1000,我就可好奇,200个线程怎么处理1000请求的,很离谱,并且一个请求就耗费一个线程了,实际上是1秒内,有可能一个请求0.5s就结束了,此时线程让出来了处理其他请求了。所以理想情况下在1s内还是有可能的,但是为什么说使用多线程也可以呢,因为这样的话,首先Tomcat的线程可以理解为我们的主线程,如何让主线程更快的释放出来,然后让它去处理别的请求,这才是我们关心的,而我们多线程刚好就解决了这个困难,首先我们自己去创建一个异步线程去处理耗时操作,这个异步线程你想创建多少个都没关系,跟Tomcat提供的那个主线程没关系,不会占用它的那200个。这样我们就让耗时操作让我们的异步线程执行,主线程就释放出来了,这样就提高了整体的并发量。

上面所说的主线程就是main线程,是由Tomcat提供的。而异步线程是jdk提供的。

所以第三可总结为:提高系统的并发处理能力

2.多线程的创建?

1.继承Thread
2.实现Runnabe接口
3.实现Callable接口
4.Executors.newFixedThreadPool

好的上面这个是标准的八股文,但实际工作中不用,1,2,3不用我说也肯定不使用,已经有线程池了,肯定使用线程池的池化思想。好处再帮各位回忆一下

1.减少频繁创建线程和销毁线程带来的额外开销,线程池可以提前帮我们创建好这些线程。

2.避免一直创建线程造成OOM,而线程池会把使用过的线程再使用,避免重复创建线程。
.......还有一些,自己下去可以会议下。
 

那上面我们都不用,但是得知道,因为面试造火箭,这些先表明你都知道,后面紧接着说,实际工作中并不会使用上面的几种方式去创建多线程,而是使用spirng给我们提供的ThreadPoolTaskExecutor或者是jdk提供的ThreadPoolExecutor,一般还是用sping提供的,毕竟现在项目都是spring家族的,IOC这么好用,必须得用上。下面上实战。

3.在代码中如何使用多线程(线程池的方式)?

我就说我在项目中看到的都是使用spring提供的ThreadPoolTaskExecutor,而并没有使用jdk提供的ThreadPoolExecutor,并不是说不可以,肯定是因为spirng提供的更简单,它提供的IOC自动注入,使用相关注解直接使用,比我们自己去创建对象更方便,也更实用。但是一定不要使用Executors.newFixedThreadPool这玩意去创建,阿里开发规范中也明确禁止,为什么禁止?

1. 隐藏关键配置参数:`Executors`提供的便捷方法通常会隐藏线程池的重要配置参数,比如线程池的大小、工作队列类型及容量、拒绝策略等。
    这限制了开发者对线程池行为的精确控制和优化,可能导致资源使用不当或性能问题。
2. 潜在的资源耗尽风险:
   (1)`newFixedThreadPool`和`newSingleThreadExecutor`使用的是无界队列(通常为`LinkedBlockingQueue`),
      这意味着如果生产任务的速度超过消费速度,队列会无限增长,最终可能导致内存耗尽(Out Of Memory Error)。
   (2)`newCachedThreadPool`创建的是一个线程数量无界的线程池,当大量短期异步任务提交时,可能会迅速创建大量线程,消耗过多系统资源

总结一句:缺少参数配置,不可控,可能会造成OOM,消耗过多的系统资源。

如何使用?

1.创建相关的配置类,起个名字,一般叫XxxThreadPoolConfig(Xxx为相关的业务的名称)

@Component
@Configuration
public class TestThreadPoolConfig {@Bean("test_thread_pool") // 设置默认线程名称public Executor ticketing() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setThreadNamePrefix("test_thread_pool-");executor.setMaxPoolSize(80); // 设置最大线程数executor.setCorePoolSize(40);//设置核心线程数executor.setQueueCapacity(100);executor.setKeepAliveSeconds(300);// 设置线程活跃时间(秒)executor.setAllowCoreThreadTimeOut(true);executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 设置拒绝策略executor.setWaitForTasksToCompleteOnShutdown(true); // 等待所有任务结束后再关闭线程池executor.initialize();return executor;}}

2.在启动类上加上开启异步的注解@EnableAsync

@SpringBootApplication
@EnableAsync
public class SystemAdminApplication {public static void main(String[] args) {SpringApplication.run(SystemAdminApplication.class,args);}
}

3.在对应的耗时接口ServiceImpl上直接使用注解@Async("xxx")xxx为配置中@Bean中的名字

 @Async("test_thread_pool")public String testThread() {try {Thread.sleep(10000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("666666666666666");return "hello";}

4.总结

为什么要使用多线程,哪些业务中用到了(实际开发业务中),怎么用的(多线程的创建方式)?

(1)处理耗时操作,提高响应速度,举例
(2)充分利用系统cpu的资源
(3)提高系统的并发量,拿上述的comcat来举例
(4)你怎么使用的?也就是项目如何用的,说我总结的第三点,具体Service业务,如果不知道怎么编,自己上网搜搜,比如发送邮件,读取文件等等,我的话肯定就是说自己项目中遇到的业务。
 

本人还是菜鸟,错误还希望大佬指点。。。。。。。
 

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

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

相关文章

PACS-医学影像信息管理系统,全影像科室PACS源码,内置包括MPR、CMPR、VR等三维处理功能

PACS系统可以覆盖医院现有放射、CT、MR、核医学、超声、内镜、病理、心电等绝大部分DICOM和非DICOM检查设备,支持从科室级、全院机、集团医院级乃至到区域PACS的平滑扩展,能够与医院HIS、集成平台的有效集成和融合,帮助医院实现了全院医学影像…

分布式 I/O 系统 BL200 Modbus TCP 耦合器

BL200 耦合器是一个数据采集和控制系统,基于强大的 32 位微处理器设计,采用 Linux 操作系统,支持 Modbus 协议,可以快速接入现场 PLC、SCADA 以及 ERP 系统, 内置逻辑控制、边缘计算应用,适用于 IIoT 和工业…

Github 2024-07-20 Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-20统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10TypeScript项目1Rust: 构建可靠高效软件的开源项目 创建周期:5064 天开发语言:Rust协议类型:OtherStar数量:92978 个Fork数量:1…

【漏洞复现】Next.js框架存在SSRF漏洞(CVE-2024-34351)

0x01 产品简介 ZEIT Next.js是ZEIT公司的一款基于Vue.js、Node.js、Webpack和Babel.js的开源Web应用框架。 0x02 漏洞概述 ZEIT Next.js 13.4版本至14.1.1之前版本存在代码问题漏洞,该漏洞源于存在服务器端请求伪造 (SSRF) 漏洞 0x03 搜索引擎 body"/_nex…

【BUG】已解决:xlrd.biffh.XLRDError: Excel xlsx file; not supported

已解决:xlrd.biffh.XLRDError: Excel xlsx file; not supported 目录 已解决:xlrd.biffh.XLRDError: Excel xlsx file; not supported 【常见模块错误】 错误原因 解决办法: 欢迎来到英杰社区https://bbs.csdn.net/…

MyBatis框架学习笔记(四):动态SQL语句、映射关系和缓存

1 动态 SQL 语句-更复杂的查询业务需求 1.1 动态 SQL-官方文档 (1)文档地址: mybatis – MyBatis 3 | 动态 SQL (2)为什么需要动态 SQL 动态 SQL 是 MyBatis 的强大特性之一 使用 JDBC 或其它类似的框架,根据不同条…

【瑞吉外卖 | day07】移动端菜品展示、购物车、下单

文章目录 瑞吉外卖 — day71. 导入用户地址簿相关功能代码1.1 需求分析1.2 数据模型1.3 代码开发 2. 菜品展示2.1 需求分析2.2 代码开发 3. 购物车3.1 需求分析3.2 数据模型3.3 代码开发 4. 下单4.1 需求分析4.2 数据模型4.3 代码开发 瑞吉外卖 — day7 移动端相关业务功能 —…

华为USG6000V防火墙NAT智能选举

目录 一、拓扑图 二、要求 三、配置思路及方法 要求1:通过多对多的NAT实现上网功能 思路:基础IP地址配置按照之前的进行配置,接着在策略里配置多对多的NAT 要求2:分公司设备可以通过总公司的移动链路和电信链路访问到Dmz区的…

uniapp中给data中的变量赋值报错

排查了一上午,原本以为是赋值的这个变量有一个键名是空字符串的问题,后来发现是因为在data中定义变量是写的是{},如果写成null就不会报错了,具体原因不清楚为什么

Spark中的JOIN机制

Spark中的JOIN机制 1、Hash Join概述2、影响JOIN的因素3、Spark中的JOIN机制3.1、Shuffle Hash Join3.2、Broadcast Hash Join3.3、Sort Merge Join3.4、Cartesian Product Join3.5、Broadcast Nested Loop Join4、Spark中的JOIN策略5、Spark JOIN机制与策略总结5.1、Spark中的…

【BUG】已解决:WslRegisterDistribution failed with error: 0x800701bc

已解决:WslRegisterDistribution failed with error: 0x800701bc 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英杰,211科班出身,就职于医疗科技公司,热衷分享知识,武…

C++初学者指南-5.标准库(第一部分)--标准库查找算法

C初学者指南-5.标准库(第一部分)–标准库查找算法 文章目录 C初学者指南-5.标准库(第一部分)--标准库查找算法查找/定位一个元素findfind_iffind_if_notfind_last / find_last_if / find_last_if_notfind_first_of 查找范围内的子范围 search find_endstarts_withends_with 找到…

1个Xpath定位可以在Web页面查找到多个元素Selenium

1个Xpath定位可以在Web页面查找到多个元素Selenium//input[id\"transactionId\"] 打开Web页面, 点击F12可以看到压面 点击Ctrl F 可以点图如下图的输入框,输入xpath,看右侧可以找到3个对应的元素 点击Ctrl F 点击Ctrl F 点…

uniapp开发钉钉小程序流程

下载开发工具 1、小程序开发工具 登录钉钉开发平台,根据自己的需求下载合适的版本,我这里下载的是Windows (64位)版本 小程序开发工具 - 钉钉开放平台 2、HBuilder X HBuilderX-高效极客技巧 新建项目及相关配置 新建项目 …

最新!CSSCI(2023-2024)期刊目录公布!

【SciencePub学术】据鲁迅美术学院7月16日消息,近日,南京大学中国社会科学研究评价中心公布了中文社会科学引文索引(CSSCI)(2023—2024)数据库最新入选目录。 C刊一般指CSSCI来源期刊,即南大核心…

通过splunk web服务将服务器上文件下载到本地

1. 需求说明 工作中经常遇到需要将服务器上的文件下载到本地,但是由于各种网络环境限制,没办法使用winscp或者xftp工具,那么如何将服务器上的文件下载下来呢? 这里提供一种思路: 如果服务器上安装有web服务,可将待下…

大语言模型-检索测评指标

1. MRR (Mean Reciprocal Rank)平均倒数排名: 衡量检索结果排序质量的指标。 计算方式: 对于每个查询,计算被正确检索的文档的最高排名的倒数的平均值,再对所有查询的平均值取均值。 意义: 衡量…

Elastic 线下 Meetup 将于 2024 年 7 月 27 号在深圳举办

2024 Elastic Meetup 深圳站活动,由 Elastic、腾讯、新智锦绣联合举办,现诚邀广大技术爱好者及开发者参加。 时间地点 2024年 7 月 27 日 13:30-18:00 活动地点 中国深圳 南山区海天二路 33 号腾讯滨海大厦 北塔 3 楼多功能厅 ​ 活动流程 14:00-15…

【你也能从零基础学会网站开发】 SQL Server 2000数据库的创建、移除、备份还原操作以及索引、视图、存储过程、触发器基本介绍!

🚀 个人主页 极客小俊 ✍🏻 作者简介:程序猿、设计师、技术分享 🐋 希望大家多多支持, 我们一起学习和进步! 🏅 欢迎评论 ❤️点赞💬评论 📂收藏 📂加关注 认识数据库中都…

GD32F303想控制PA13~15、PB3和PB4不成功?

有没有小伙伴遇到这种情况:在使用GD32F303的时候,想要将PA13~15以及PB3和PB4作为IO口来使用,却怎么也不成功呢?下面小编就来告诉大家原因。 我们先来看下GD32F303 datasheet中这几个引脚的定义: 原来,这几…