当前位置: 首页 > news >正文

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业务,如果不知道怎么编,自己上网搜搜,比如发送邮件,读取文件等等,我的话肯定就是说自己项目中遇到的业务。
 

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

相关文章:

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

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

kafka集群搭建-使用zookeeper

1.环境准备: 使用如下3台主机搭建zookeeper集群,由于默认的9092客户端连接端口不在本次使用的云服务器开放端口范围内,故端口改为了8093。 172.2.1.69:8093 172.2.1.70:8093 172.2.1.71:8093 2.下载地址 去官网下载,或者使用如…...

【python】Numpy运行报错分析:IndexError与形状不匹配问题

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

你有多自律就有多自由

当你失去对时间的控制权,生活也就失去了平衡。 真正对自己有要求的人,都是高度自律的人。 追求自己想要的生活,任何时候开始都不会晚,关键在于你能够坚持下去,以高度自律的精神,日复一日、年复一年的坚持下…...

Codeforces Round 959 (Div. 1 + Div. 2 ABCDEFG 题) 文字讲解+视频讲解

Problem A. Diverse Game Statement 给定 n m n\times m nm 的矩形 a a a, a a a 中的每一个数均在 1 ∼ n m 1\sim nm 1∼nm 之间且互不相同。求出 n m n\times m nm 的矩形 b b b, b b b 中的每一个数均在 1 ∼ n m 1\sim nm 1∼nm 之间且互…...

WSL2 Centos7 Docker服务启动失败怎么办?

wsl 安装的CentOS7镜像,安装了Docker之后,发现用systemctl start docker 无法将docker启动起来。 解决办法 1、编辑文件 vim /usr/lib/systemd/system/docker.service将13行注释掉,然后在下面新增14行的内容。然后保存退出。 2、再次验证 可以发现,我们已经可以正常通过s…...

分布式锁-redisson锁重试和WatchDog机制

抢锁过程中,获得当前线程,通过tryAcquire进行抢锁,该抢锁逻辑和之前逻辑相同。 1、先判断当前这把锁是否存在,如果不存在,插入一把锁,返回null 2、判断当前这把锁是否是属于当前线程,如果是&a…...

ESP8266模块(2)

实例1 查看附近的WiFi 步骤1:进入AT指令模式 使用USB转串口适配器将ESP8266模块连接到电脑。打开串口终端软件,并设置正确的串口和波特率(通常为115200)。输入以下命令并按回车确认: AT如果模块响应OK,…...

Docker安装笔记

1. Mac安装Docker 1.1 Docker安装包下载 1.1.1 阿里云 对于10.10.3以下的用户 推荐使用 对于10.10.3以上的用户 推荐使用 1.1.2 官网下载 系统和芯片选择适合自己的安装包 1.2 镜像加速 【推荐】阿里镜像 登陆后,左侧菜单选中镜像加速器就可以看到你的专属地…...

《昇思25天学习打卡营第21天|Pix2Pix实现图像转换》

Pix2Pix 是一种图像转换模型,使用条件生成对抗网络(Conditional Generative Adversarial Networks,cGANs)实现图像到图像的转换。它主要由生成器(Generator)和判别器(Discriminator)…...

Python和MATLAB网络尺度结构和幂律度大型图生成式模型算法

🎯要点 🎯算法随机图模型数学概率 | 🎯图预期度序列数学定义 | 🎯生成具有任意指数的大型幂律网络,数学计算幂律指数和平均度 | 🎯随机图分析中巨型连接分量数学理论和推论 | 🎯生成式多层网络…...

在jsPsych中使用Vue

jspsych 介绍 jsPsych是一个非常好用的心理学实验插件,可以用来构建心理学实验。具体的就不多介绍了,大家可以去看官网:https://www.jspsych.org/latest/ 但是大家在使用时就会发现,这个插件只能使用js绘制界面,或者…...

机器学习·概率论基础

概率论 概率基础 这部分太简单,直接略过 条件概率 独立性 独立事件A和B的交集如下 非独立事件 非独立事件A和B的交集如下 贝叶斯定理 先验 事件 后验 在概率论和统计学中,先验概率和后验概率是贝叶斯统计的核心概念 简单来说后验概率就是结合了先验概…...

c生万物系列(面向对象:封装)

本系列博客主要介绍c语言的一些屠龙技,里面包含了笔者本人的一些奇思妙想。 该系列博客笔者只是用作记录。如果你偶然找到了这篇博客,但是发现不知所云,请不要过多投入时间,可能笔者本人那时候也看不懂了。 笔者决定用c语言模仿…...

当当网数据采集:Scrapy框架的异步处理能力

在互联网数据采集领域,Scrapy框架以其强大的异步处理能力而著称。Scrapy利用了Python的异步网络请求库,如twisted,来实现高效的并发数据采集。本文将深入探讨Scrapy框架的异步处理能力,并展示如何在当当网数据采集项目中应用这一能…...

React——useEffect和自定义useUpdateEffect

useEffect 是React的一个内置Hook,用于在组件渲染后执行副作用(例如数据获取、订阅或手动更改DOM)。它将在第一次渲染后和每次更新后都会执行。 useEffect(() > {// 这里的代码将在组件挂载和更新时执行。 }, [dependencies]); // depend…...

Hadoop大数据处理架构中ODB、DIM、DWD、DWS

在Hadoop的大数据处理架构中,ODS、DIM、DWD和DWS分别代表了数据仓库体系中不同的层次和功能。下面解释这几个概念: ODS (Operational Data Store) 想象你有一家超市,每天营业结束后,你会把当天所有的销售记录、顾客信息、商品库…...

【刷题汇总 -- 爱丽丝的人偶、集合、最长回文子序列】

C日常刷题积累 今日刷题汇总 - day0211、爱丽丝的人偶1.1、题目1.2、思路1.3、程序实现 2、集合2.1、题目2.2、思路2.3、程序实现 -- set 3、最长回文子序列3.1、题目3.2、思路3.3、程序实现 -- dp 4、题目链接 今日刷题汇总 - day021 1、爱丽丝的人偶 1.1、题目 1.2、思路 …...

基于vue3 + vite产生的 TypeError: Failed to fetch dynamically imported module

具体参考这篇衔接: Vue3报错:Failed to fetch dynamically imported module-CSDN博客 反正挺扯淡的,错误来源于基于ry-vue-plus来进行二次开发的时候遇到的问题。 错误起因 我创建了一个广告管理页面。然后发现访问一直在加载中。报的是这样…...

批量自动添加好友,高效拓展人脉圈.

随着微信使用数量的不断增加,手动添加好友成为了一项耗时且繁琐的任务。为了帮助大家解决这个问题,下面分享一款高效的微信管理系统,它能够帮助你实现批量自动添加好友,极大提升了人脉拓展的效率。 这款微信管理系统可以同时管理多…...

Web开发:一个可拖拽的模态框(HTML、CSS、JavaScript)

目录 一、需求描述 二、实现效果 三、完整代码 四、实现过程 1、HTML 页面结构 2、CSS 元素样式 3、JavaScript动态控制 (1)获取元素 (2)显示\隐藏遮罩层与模态框 (3)实现模态框拖动效果 一、需求…...

【深度学习】fooocusapi,docker,inpainting图像

基础镜像制作来源 fooocusapi接口官方写的: docker run -d --gpusall \-e NVIDIA_DRIVER_CAPABILITIEScompute,utility \-e NVIDIA_VISIBLE_DEVICESall \-p 8888:8888 konieshadow/fooocus-api会下载一些模型,下载完后推这个镜像 docker commit 4dfd1…...

算法017:二分查找

二分查找. - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/binary-search/ 二分查找,其实是双指针的一种特殊情况,但是时间复杂度极低&#…...

谷粒商城实战笔记-37-前端基础-Vue-基本语法插件安装

文章目录 一,v-model1,双向绑定2,vue的双向绑定2.1 html元素上使用指令v-model2.2 model中声明对应属性2.3,验证view绑定modelmodel绑定view 完整代码 二,v-on1,指令简介2,在button按钮中添加v-…...

mybatis中的缓存(一级缓存、二级缓存)

文章目录 前言一、MyBatis 缓存概述二、一级缓存1_初识一级缓存2_一级缓存命中原则1_StatementId相同2_查询参数相同3_分页参数相同4_sql 语句5_环境 3_一级缓存的生命周期1_缓存的产生2_缓存的销毁3_网传的一些谣言 4_一级缓存核心源码5_总结 三、二级缓存1_开启二级缓存2_二级…...

实现自动化采购:食堂采购系统源码开发详解

本篇文章,笔者将详细介绍食堂采购系统的开发过程,从需求分析、系统设计到实现和测试,为您全面解析如何构建一个高效的自动化采购系统。 一、需求分析 1.采购计划管理 2.供应商管理 3.订单管理 4.库存管理 5.财务管理 6.数据分析与报告 …...

linux、windows、macos清空本地DNS缓存

文章目录 Linux:Windows:macOS: Linux: 对于使用systemd的操作系统(如CentOS 7、Ubuntu 16.04),可以使用以下命令重启systemd-resolved服务来清除缓存: sudo systemctl restart sys…...

领夹麦克风哪个品牌好,电脑麦克风哪个品牌好,热门麦克风推荐

​在信息快速传播的时代,直播和视频创作成为了表达与交流的重要方式。对于追求卓越声音品质的创作者而言,一款性能卓越的无线麦克风宛如一把利剑。接下来,我要为大家介绍几款备受好评的无线麦克风,这些都是我在实际使用中体验良好…...

【第5章】Spring Cloud之Nacos服务注册和服务发现

文章目录 前言一、提供者1. 引入依赖2.配置 Nacos Server 地址3. 开启服务注册 二、消费者1. 引入依赖2.配置 Nacos Server 地址3. 开启服务注册 三、服务列表四、服务发现1. 获取服务列表2. 测试2.1 获取所有服务2.2 根据服务名获取服务信息 五、更多配置项总结 前言 本节通过…...

Springboot 启动时Bean的创建与注入(一)-面试热点-springboot源码解读-xunznux

Springboot 启动时Bean的创建与注入,以及对应的源码解读 文章目录 Springboot 启动时Bean的创建与注入,以及对应的源码解读构建Web项目流程图:堆栈信息:堆栈信息简介堆栈信息源码详解1、main:10, DemoApplication (com.xun.demo)2…...

网站后台 灰色/北京本地网络推广平台

欢迎加入学习python的队伍,我们非常欢迎,一起学习,一起进步!!!转载于:https://www.cnblogs.com/xiaohaiying/p/7169017.html...

手机网站图片自适应代码/关键词优化排名

文章目录一、对《青春有你2》的参赛选手区域进行可视化分析二、爬《青春有你2》的参赛选手体重进行可视化分析一、对《青春有你2》的参赛选手区域进行可视化分析 """ 对《青春有你2》的参赛选手区域进行可视化分析 """ import matplotlib.pyplo…...

各级政府网站建设有待加强/seo优化关键词排名优化

文章目录1. 简介1.1 特性1.2 组件1.3 版本2. 安装部署2.1 安装说明2.2 centos7安装2.3 Debian&Ubuntu3. 运行docker3. docker基本操作3.1 容器操作3.1.1 启动容器3.1.2. 查看容器3.1.3 查看容器具体信息3.1.4 停止容器3.1.5 启动已停止的容器3.1.6 删除容器3.1.7 暂停某个容…...

上海门户网站制作/360社区app

http://dbconvert.com转载于:https://blog.51cto.com/gjbxx110/515802...

郑州做网站哪个/长治网站seo

display属性规定元素应该生成的框的类型;position属性规定元素的定位类型;float属性是一种布局方式,定义元素在哪个方向浮动。类似于优先级机制:position:absolute/fixed优先级最高,有他们在时,…...

河池网站建设公司/培训方案模板

Golang分段锁介绍代码介绍 因为golang的原生map是非并发安全的,所以为了保证map的并发安全,最简单的方式就是给map加锁。直接对一个map加锁,当访问map的请求越来越多,都竞争这一把锁使得并发访问变慢。 分段锁是一种锁的设计&am…...