多线程的使用(springboot)
预备知识
业务使用多线程的原因
- 目的是面对高并发的时候,提高运行速度
场景一:
一个业务逻辑有很多次的循环,每次循环之间没有影响,比如验证1万条url路径是否存在,正常情况要循环1万次,逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。这时可以用多线程,将1万条URL分成50等份,开50个线程,没个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。
场景二:
需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个业务逻辑执行效率特别低,耗时特别长,就可以考虑使用多线程。
问题:不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级,因此使用多线程的风险也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!
项目中可以通过:
@Order()
设置运行的优先级,数字越小,级别越高
FutureTask介绍
参考: (101条消息) FutureTask详解_索码理的博客-CSDN博客_futuretask
线程池为什么要使用阻塞队列
阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使得线程进入wait 状态,释放 cpu 资源,当队列中有任务时才唤醒对应线程从队列中取出消息进行执行。
使得在线程不至于一直占用cpu资源。(线程执行完任务后通过循环再次从任务队列中取出任务进行执行,代码片段如:while (task != null || (task = getTask()) != null) {})。
不用阻塞队列也是可以的,不过实现起来比较麻烦而已,有好用的为啥不用呢
Spring线程池
介绍:
Spring 通过任务执行器(TaskExecutor)来实现多线程和并发编程,使用 ThreadPoolTaskExecutor 实现一个基于线程池的TaskExecutor,
还得需要使用 @EnableAsync 开启异步,并通过在需要的异步方法那里使用注解@Async声明是一个异步任务
Spring 已经实现的异常线程池:
- SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。
- SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方
- ConcurrentTaskExecutor:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类
- SimpleThreadPoolTaskExecutor:是Quartz的 SimpleThreadPool 的类。线程池同时被quartz和非quartz使用,才需要使用此类
- ThreadPoolTaskExecutor :最常使用,推荐。 其实质是对 java.util.concurrent.ThreadPoolExecutor 的包装
同步使用
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
FutureTask<List> commentCallable = new FutureTask<>(GrouponRulesCallable);
Future<Map> submit = executor.submit(commentCallable);
Map map = submit.get();
异步的使用:
[(101条消息) SpringBoot实现多线程_喜欢前端的后端MelodyJerry的博客-CSDN博客_springboot实现多线程](https://blog.csdn.net/weixin_43438052/article/details/116108860#:~:text=SpringBoot实现 多线程 1 SpringBoot通过 任务执行器TaskExecutor 来实现多线程和并发编程。 2 使用,%40EnableAsync 开启对 异步任务 的支持,并通过在实际执行的Bean中的方法使用 %40Async注解 来声明这是一个 异步任务 。)
JUC 的线程池
并发下使用同步线程
具体代码参考: litemall示例代码
- 声明
private final static ArrayBlockingQueue<Runnable> WORK_QUEUE= new ArrayBlockingQueue<>(9);
// handler – 由于达到线程边界和队列容量而阻塞执行时使用的处理程序
private final static RejectedExecutionHandler HANDLER=new ThreadPoolExecutor.CallerRunsPolicy();
private static ThreadPoolExecutor executorService = new ThreadPoolExecutor(16, 16, 1000, TimeUnit.MILLISECONDS, WORK_QUEUE, HANDLER);
- 使用,通过 get() 方法获取他的返回值
// 商品属性
Callable<List> listCallable =()->goodsAttributeService.getGoodsAttributeList(litemallGoods.getGoodsSn());
// 商品规格
Callable<Object> specificationCallable =()-> specificationService.getGoodsSpecification(litemallGoods.getGoodsSn());
FutureTask<List> goodsAttributeListTask = new FutureTask<>(listCallable);
FutureTask<Object> objectCallableTask = new FutureTask<>(specificationCallable);
executorService.submit(goodsAttributeListTask);
executorService.submit(objectCallableTask);
多线程的使用(springboot)的更多相关文章
- SpringBoot:实现定时任务
一.定时任务实现的几种方式: Timer 这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执 ...
- springboot 多线程执行
一.springboot开线程执行异步任务 1.Spring通过任务执行器TaskExecutor,来实现多线程和并发编程,使用ThreadPoolTaskExecutor可实现一个基于线程池的Tas ...
- springboot下多线程开发注意事项
基于springboot的多线程程序开发过程中,由于本身也需要注入spring容器进行管理,才能发挥springboot的优势.所以这篇文字主要用来记录开发中两者结合时需要注意的一些事项. 第一步我们 ...
- 关于java基础、多线程、JavaWeb基础、数据库、SSM、Springboot技术汇总
作者 : Stanley 罗昊 本人自行总结,纯手打,有疑问请在评论区留言 [转载请注明出处和署名,谢谢!] 一.java基础 1.多态有哪些体现形式? 重写.重载 2. Overriding的是什么 ...
- 转载-SpringBoot结合线程池解决多线程问题实录;以及自己的总结
原文地址:https://blog.csdn.net/GFJ0814/article/details/92422245 看看这篇文章(继续学习):https://www.jianshu.com/p/3 ...
- SpringBoot Test 多线程报错:dataSource already closed
1:前言 最近在项目中使用多线程对大任务拆分处理时,进行数据库操作的时候报错了. 业务代码大概是这样的: @Service public calss TestServiceImpl implement ...
- SpringBoot中如何优雅的使用多线程
SpringBoot中如何优雅的使用多线程 当异步方法有返回值时,如何获取异步方法执行的返回结果呢?这时需要异步调用的方法带有返回值CompletableFuture
- SpringBoot 多线程
Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程.使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor.而实际开发中任务一般是非阻 ...
- SpringBoot几种定时任务的实现方式 和多线程执行任务
定时任务实现的几种方式: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行, ...
随机推荐
- YII学习总结1
YII 安装(2.0 advanced) 以下借鉴别人的博文 http://www.jb51.net/article/54055.htm 今天终于搞明白怎么安装Yii2了.对于我这种小白来说真是费尽 ...
- odoo 14 一些常见问题集
1 # 当你往tree或者form视图中增加action的时候 2 # 记住!千万别重名 3 # 一旦重名,Export.Delete.Archive.Unarchive都会消失不见 4 # tree ...
- Odoo14 给模块/应用加小图标
# apps中的图标是固定路劲: static/description/icon.png # 主页图标是通过你的主menuitem的web_icon来设置的: <menuitem id=&quo ...
- 【AGC】增长服务1-远程配置示例
[AGC]增长服务1-远程配置示例 前言:上一次笔者给大家带来了AGC领域的性能管理服务的学习.这次我们再继续深化学习AGC的相关知识.在文章开始之前,再给读者简单介绍一下AGC,以免第一次来的读 ...
- C++封装静态链接库和使用
零碎记事 距离上次发博客已经有一年半了,转眼间我也是从做图像研究到了做游戏开发,说起来看看前面的博文,本来就有前兆的东西呢(笑)......因为主要还是在使用虚幻引擎,所以C++的东西会碰到多一些. ...
- 大数据工作流任务调度--有向无环图(DAG)之拓扑排序
点击上方蓝字关注DolphinScheduler(海豚调度) |作者:代立冬 |编辑:闫利帅 回顾基础知识: 图的遍历 图的遍历是指从图中的某一个顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点 ...
- Rust 从入门到精通05-数据类型
Rust 是 静态类型(statically typed)语言,也就是说在编译时就必须知道所有变量的类型. 在 Rust 中,每一个值都属于某一个 数据类型(data type),分为两大类: ①.标 ...
- NOI 2019 省选模拟赛 T1【JZOJ6082】 染色问题(color) (多项式,数论优化)
题面 一根长为 n 的无色纸条,每个位置依次编号为 1,2,3,-,n ,m 次操作,第 i 次操作把纸条的一段区间 [l,r] (l <= r , l,r ∈ {1,2,3,-,n})涂成颜色 ...
- hadoop 不在 sudoers 文件中,此事将被报告。
问题来源: 使用sudo命令,让hadoop用户使用root身份执行命令时报错: [hadoop@mydocker ~]$ sudo date [sudo] password for hadoop: ...
- Qt 场景创建
1 创建 Q t Widget Application 2 创建窗口 3 创建后的目录 创建完成后运行一下 4 导入资源 将res文件拷贝到 项目工程目录下 添加资源 选择一模版.Qt-Reso ...