当前位置: 首页 > 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来进行二次开发的时候遇到的问题。 错误起因 我创建了一个广告管理页面。然后发现访问一直在加载中。报的是这样…...

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

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

基础测试工具使用经验

背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

Robots.txt 文件

什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

ios苹果系统,js 滑动屏幕、锚定无效

现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

2023赣州旅游投资集团

单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

软件工程 期末复习

瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...

Vue 3 + WebSocket 实战:公司通知实时推送功能详解

📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...