线程池详解与异步任务编排使用案例

news/2024/4/29 5:47:30/文章来源:https://blog.csdn.net/doomwatcher/article/details/127272313

线程池详解与异步任务编排使用案例

1.初始化线程的4种方式

1)、继承Thread
2)、实现 Runnable接口
3)、实现 Callable接口+FutureTask(可以拿到返回结果,可以处理异常)
4)、线程池区别:12不能得到返回值。3可以获取返回值123都不能控制资源(无法控制线程数【高并发时线程数耗尽资源】)4可以控制资源,性能稳定,不会一下子所有线程一起运行结论:实际开发中,只用线程池【高并发状态开启了n个线程,会耗尽资源】

2.创建线程池的方式

创建固定线程数的线程池ExecutorService

固定线程数的线程池
Executors.newFixedThreadPool(10);

execute和submit区别

作用:都是提交异步任务的execute:只能提交Runnable任务,没有返回值
submit:可以提交Runnable、Callable,返回值是FutureTask

创建原生线程池ThreadPoolExecutor

new ThreadPoolExecutor(5,200,10,TimeUnit.SECONDS,new LinkedBlockingDeque<>(100000),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());7个参数:corePoolSize:	核心线程数,不会被回收,接收异步任务时才会创建maximumPoolSize:最大线程数量,控制资源keepAliveime: 	maximumPoolSize-corePoolSize 无任务存活超过空闲时间则线程被释放TimeUnitunit:	时间单位workQueue:		阻塞队列,任务被执行之前保存在任务队列中,只要有线程空闲,就会从队列取出任务执行threadFactory:	线程的创建工厂【可以自定义】RejectedExecutionHandler handler:队列满后执行的拒绝策略线程池任务执行流程当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理(默认策略抛出异常)当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,释放空闲线程当设置allowCoreThreadTimeOut(true)时,该参数默认false,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

拒绝策略

DiscardOldestPolicy:丢弃最老的任务
AbortPolicy:丢弃当前任务,抛出异常【默认策略】
CallerRunsPolicy:同步执行run方法
DiscardPolicy:丢弃当前任务,不抛出异常

1637156049353

阻塞队列

1.new LinkedBlockingDeque<>();// 默认大小是Integer.Max会导致内存不足,所以要做压力测试给出适当的队列大小

1637155709249

线程池

1.常见的4种默认线程池

注意:回收线程 = maximumPoolSize - corePoolSize可缓冲线程池【CachedThreadPool】:corePoolSize=0, maximumPoolSize=Integer.MAX_VALUE
定长线程池【FixedThreadPool】:corePoolSize=maximumPoolSize
周期线程池【ScheduledThreadPool】:指定核心线程数,maximumPoolSize=Integer.MAX_VALUE,支持定时及周期性任务执行(一段时间之后再执行)
单任务线程池【SingleThreadPool】:corePoolSize=maximumPoolSize=1,从队列中获取任务(一个核心线程)Executors.newCachedThreadPool();
Executors.newFixedThreadPool(10);
Executors.newScheduledThreadPool(10);
Executors.newSingleThreadExecutor();

2.为什么使用线程池?

1.降低资源的消耗【减少创建销毁操作】通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗高并发状态下过多创建线程可能将资源耗尽
2.提高响应速度【控制线程个数】因为线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务的状态,当任务来时无需创建新的线程就能执行(线程个数过多导致CPU调度慢)
3、提高线程的可管理性【例如系统中可以创建两个线程池,核心线程池、非核心线程池【例如发送短信】,显存告警时关闭非核心线程池释放内存资源】线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使用线程池进行统一分配

异步编排CompletableFuture

1.runXXX都是没有返回结果的,supplyXXX可以获取返回结果
2.可以传入自定义线程池,否则使用默认线程池

1.业务场景

4、5、6依赖1,得先知道sku是哪个spu下的

1637157703655

1637157780124

1637157807032

2.测试异步操作

supplyAsync

// 5.1.提交任务异步执行(supplyAsync)
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "测试使用", executor);
System.out.println(future1.get());

1637158218115

thenRunAsync串行化

// 不能获取上一步结果 + 无返回值

thenAcceptAsync串行化

// 能获取上一步结果 + 无返回值

thenApplyAsync串行化

// 能获取上一步结果 + 有返回值
// 5.2.获取上一步结果并链式异步调用(thenApplyAsync)
CompletableFuture<String> future2 = future1.thenApplyAsync(s -> s + " 链式调用", executor);// 参数s是上一步的返回值
System.out.println(future2.get());

whenCompleteAsync

// 5.3.获取上一步执行结果并获取异常信息(whenCompleteAsync)【无法处理异常返回默认值】
CompletableFuture<String> future3 = future2.whenCompleteAsync((result, exception) -> System.out.println("结果是:" + result + "----异常是:" + exception));

exceptionally

// 5.4.获取上一步异常,如果出现异常可返回默认值,不出现异常保持原值(exceptionally)
CompletableFuture<Integer> future4 = future3.thenApplyAsync((s -> 1 / 0), executor);
CompletableFuture<Integer> future5 = future4.exceptionally(exception -> {
System.out.println("出现异常:" + exception);
return 10;
});// 出现异常,使用默认返回值
System.out.println("默认值:" + future5.get());

handle

// 5.5.方法执行完成后的处理
CompletableFuture<Integer> future6 = future3.thenApplyAsync((s -> 1 / 0), executor).handle((result, exception) -> {if (exception == null) {return result;}System.out.println("handle处理异常:" + exception);return 1;
});
System.out.println("handle处理返回结果:" + future6.get());

两任务组合-都要完成

1637162227217

1637162027844

runAfterBothAsync

// 5.6.1.二者都要完成,组合【不获取前两个任务返回值,且自己无返回值】
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {System.out.println("任务1执行");return 10 / 2;
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {System.out.println("任务2执行");return "hello";
}, executor);
CompletableFuture<Void> future03 = future01.runAfterBothAsync(future02, () -> {System.out.println("任务3执行");
}, executor);

thenAcceptBothAsync

// 5.6.2.二者都要完成,组合【获取前两个任务返回值,自己无返回值】
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {System.out.println("任务1执行");return 10 / 2;
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {System.out.println("任务2执行");return "hello";
}, executor);
CompletableFuture<Void> future03 = future01.thenAcceptBothAsync(future02,(result1, result2) -> {System.out.println("任务3执行");System.out.println("任务1返回值:" + result1);System.out.println("任务2返回值:" + result2);}, executor);

thenCombineAsync

// 5.6.3.二者都要完成,组合【获取前两个任务返回值,自己有返回值】
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {System.out.println("任务1执行");return 10 / 2;
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {System.out.println("任务2执行");return "hello";
}, executor);
CompletableFuture<String> future03 = future01.thenCombineAsync(future02,(result1, result2) -> {System.out.println("任务3执行");System.out.println("任务1返回值:" + result1);System.out.println("任务2返回值:" + result2);return "任务3返回值";}, executor);
System.out.println(future03.get());

两任务组合-任一完成

1637163146554

1637163163732

runAfterEitherAsync

// 不获取前任务返回值,且当前任务无返回值

acceptEitherAsync

// 获取前任务返回值,但当前任务无返回值

applyToEitherAsync

// 获取前任务返回值,当前任务有返回值

多任务组合

allOf

// 等待所有任务完成
CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
allOf.get();// 阻塞等待所有任务完成

anyOf

CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future01, future02, future03);
anyOf.get();// 阻塞等待任一任务完成,返回值是执行成功的任务返回值

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

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

相关文章

b站pink老师JavaScript的jQuery 案例代码——电梯导航案例

目录 代码部分&#xff1a; 1.index.js&#xff08;全是重点&#xff09; 2.index.html&#xff08;辅助作用&#xff0c;用于查看结构&#xff09; 3.index.css&#xff08;辅助作用&#xff0c;用于设置一开始的电梯导航display:none&#xff09; 4.jquery.min.js&#x…

Graph Representation Learning Chapter[3]

本章学习节点嵌入。这些方法的目标是将节点编码为低维向量&#xff0c;以表示它们的图位置和局部图邻域的结构。换句话说&#xff0c;我们希望将节点投影到一个潜在空间中&#xff0c;其中这个潜在空间中的几何关系对应于原始图或网络中的关系。 几篇文章&#xff0c;强烈建议观…

行为树BT设计与实现

行为树BT设计与实现1 介绍2 汇总From McYY整体结构运行逻辑节点共享数据中断的实现From AKaraFrom Luyu HuangFrom 阿高From xiyoo0812参考1 介绍 状态机与行为树BT 2 汇总 From McYY lua行为树设计与实现 LuaBT 项目需要&#xff0c;之前行为树用的是behaviorDesigner&…

数据科学的统计学知识笔记

1.描述统计 1.数字特征&#xff08;描述统计&#xff09; 集中趋势 众数中位数四分位数平均数&#xff1a;样本平均数&#xff08;xˉ\bar{x}xˉ&#xff09;与总体平均数&#xff08;μ\muμ&#xff09; 离中趋势&#xff08;离散趋势&#xff09;异众比率&#xff1a;非众…

scratch加法出题器 电子学会图形化编程scratch等级考试三级真题和答案解析2022年9月

目录 scratch加法出题器 一、题目要求 1、准备工作 2、功能实现 二、案例分析 <

『LeetCode|每日一题』---->二叉搜索树中第K小的元素

目录 1.每日一句 2.作者简介 3.二叉搜索树简介 『LeetCode|每日一题』二叉搜索树中第K小的元素 1.每日一题 4.解题思路 4.1 思路分析 4.2 核心代码 4.3 完整代码 4.4 运行结果 1.每日一句 因为时间永远分岔&#xff0c;通往无数的未来 2.作者简介 &#x1f3e1;个人主页&…

如何着手写一篇医学综述?

各位医学研究生&#xff0c;研0的时候是不是导师都已经把综述布置下来作为你的第一份作业呀&#xff1f;对于医学生们来说&#xff0c;不管你是本科就已经开始接触科研还是研究生开始才接触科研&#xff0c;反正在你开始阅读文献的时候开始一篇综述总是逃不过的。鉴于有综述任务…

Sql Server CDC配置

概述 CDC&#xff08;Change Data Capture&#xff09;&#xff0c;即数据变更抓取&#xff0c;通过为源端数据源开启CDC&#xff0c;ROMA Connect可实现数据源的实时数据同步以及数据表的物理删除同步。 本章节主要介绍如何为SQL Server数据库开启CDC功能。 前提条件 SQL S…

算力是新一代的“石油”,我们该如何利用好它?

我们处在一个数字世界&#xff0c;计算能力成为科技进步和经济发展的底座&#xff0c;也正在改变我们的生产方式和生活方式。未来&#xff0c;几万台、几十万台甚至几亿台服务器&#xff0c;如果都能够基于一个操作系统进实时调度&#xff0c;将带来巨大的算力提升。我们这一代…

【Linux高效小trick】快速查看Linux进程的开始和运行时间

写在前面 前面介绍了&#xff0c;怎么杀死Linux的僵尸进程&#xff0c;为GPU释放更多的内存&#xff0c;做想做的事&#xff0c;文章链接如下&#xff1a; 【Linux高效小trick】Linux下杀死僵尸进程&#xff0c;释放GPU内存&#xff0c;让代码全速运行~ 今天再来具体说下&…

Jetpack 之 ViewModel

Jetpack 系列第三篇&#xff0c;这次回顾 ViewModel&#xff0c;ViewModel 作为 MVVM 架构中的 VM 层&#xff0c;具有自己的生命周期&#xff0c;且生命周期贯穿整个 Activity 或 Fragment&#xff0c;相较于之前 MVP 的 Presenter&#xff0c;它的存活时间更长&#xff0c;所…

商用图片素材,高清无水印

今天给大家分享8个免费、商用图片素材网站&#xff0c;全部高清无水印&#xff0c;轻松应对各种场景。1、菜鸟图库 https://www.sucai999.com/pic.html?vNTYwNDUx菜鸟图库是一个综合性素材网站&#xff0c;这里面有很多设计、图片、视频、音频等素材&#xff0c;图片素材全部都…

vscode 提示 vetur can‘t find `tsconfig.json`的解决办法

VSCode&#xff08;全称&#xff1a;Visual Studio Code&#xff09;是一款由微软开发且跨平台的免费源代码编辑器。该软件支持语法高亮、代码自动补全&#xff08;又称 IntelliSense&#xff09;、代码重构、查看定义功能&#xff0c;并且内置了命令行工具和 Git 版本控制系统…

SEO作弊有哪些手段,网站采用SEO作弊会带来哪些惩罚

在做网站SEO优化过程中&#xff0c;有的人为了快速提高网站排名&#xff0c;采用了各种各样的方法。有的甚至采用SEO作弊的手段来优化网站&#xff0c;短期内提升了网站的排名。但是&#xff0c;我们要知道&#xff0c;做SEO优化欲速则不达&#xff0c;SEO作弊会给网站带来一定…

部署CentOS可视化界面GUI-之腾讯云服务器

目录 一、购买云服务器实例 二、配置安全组、设置管理员密码 三、远程登录 四、安装CentOS可视化界面GUI 4.1、系统GUI配置 4.2、系统GUI配置 一、购买云服务器实例 二、配置安全组、设置管理员密码 三、远程登录 用其控制台下webShell&#xff0c;或VNC模式&#xff0…

《MySQL实战45讲》——学习笔记08 “一致性视图、可重复读实现“

这篇文章讲的比较分散&#xff0c;这里做一个梳理&#xff0c;先将简单的概念如"事务的启动时机"、"视图"、"秒级创建快照"拎出来解释&#xff0c;然后通过文章中的几个例子说明"一致性读"和"当前读"&#xff1b; 08 | …

AspectJ in action

Discovering AOP This chapter covers ■ Understanding crosscutting concerns ■ Modularizing crosscutting concerns using AOP ■ Understanding AOP languages Reflect back on your last project, and compare it with a project you worked on a few years back. Wha…

一文带你快速鉴别CookieSession

文章目录会话跟踪技术1、相关基础概念2、Cookie2.1 Cookie的基本使用2.1.1 发送Cookie2.1.2 获取Cookie2.2 Cookie原理2.3 Cookie存活时间2.4 Cookie存储中文3、Session3.1 Session的基本使用3.2 Session原理3.3 Session的钝化和活化3.4 Session的存活时间总结会话跟踪技术 1、…

SSl证书协议作用

SSl证书协议作用 随着移动互联网时代的飞速发展&#xff0c;似乎每周都能看到很多关于数据泄露的新闻&#xff0c;而且报道还在不断涌现。在统计的100款app中&#xff0c;有多达91款app收集了过多的用户个人信息。 为了改善这一现象&#xff0c;网络空间管理局联合发布了《认定…

TRC丨艾美捷TRC 2-氨基-2-甲基丙酰胺说明书

艾美捷TRC 2-氨基-2-甲基丙酰胺化学性质&#xff1a; 目录号A010210 化学名称2-氨基-2-甲基丙酰胺 CAS 编号16252-90-7 分子式C₄H₁₀N2O 外貌白色固体 熔点>250C&#xff08;分解&#xff09; 分子量102.14 溶解度甲醇&#xff08;少量&#xff09; 类别建筑模块…