预备知识

业务使用多线程的原因

  • 目的是面对高并发的时候,提高运行速度

场景一:

一个业务逻辑有很多次的循环,每次循环之间没有影响,比如验证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)的更多相关文章

  1. SpringBoot:实现定时任务

    一.定时任务实现的几种方式: Timer 这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执 ...

  2. springboot 多线程执行

    一.springboot开线程执行异步任务 1.Spring通过任务执行器TaskExecutor,来实现多线程和并发编程,使用ThreadPoolTaskExecutor可实现一个基于线程池的Tas ...

  3. springboot下多线程开发注意事项

    基于springboot的多线程程序开发过程中,由于本身也需要注入spring容器进行管理,才能发挥springboot的优势.所以这篇文字主要用来记录开发中两者结合时需要注意的一些事项. 第一步我们 ...

  4. 关于java基础、多线程、JavaWeb基础、数据库、SSM、Springboot技术汇总

    作者 : Stanley 罗昊 本人自行总结,纯手打,有疑问请在评论区留言 [转载请注明出处和署名,谢谢!] 一.java基础 1.多态有哪些体现形式? 重写.重载 2. Overriding的是什么 ...

  5. 转载-SpringBoot结合线程池解决多线程问题实录;以及自己的总结

    原文地址:https://blog.csdn.net/GFJ0814/article/details/92422245 看看这篇文章(继续学习):https://www.jianshu.com/p/3 ...

  6. SpringBoot Test 多线程报错:dataSource already closed

    1:前言 最近在项目中使用多线程对大任务拆分处理时,进行数据库操作的时候报错了. 业务代码大概是这样的: @Service public calss TestServiceImpl implement ...

  7. SpringBoot中如何优雅的使用多线程

    SpringBoot中如何优雅的使用多线程 当异步方法有返回值时,如何获取异步方法执行的返回结果呢?这时需要异步调用的方法带有返回值CompletableFuture

  8. SpringBoot 多线程

    Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程.使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor.而实际开发中任务一般是非阻 ...

  9. SpringBoot几种定时任务的实现方式 和多线程执行任务

    定时任务实现的几种方式: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行, ...

随机推荐

  1. 函数,递归以及dom简单操作

    函数 函数概述 函数就是具备某个功能的一个工具.是完成某个功能的一段代码. 系统提供了很多函数,但是并不能包含所有的功能,所以有些功能需要我们自己来写----自定义函数.函数定义好以后,就可以像系统函 ...

  2. eplan中数据库运行提速

    access,sql,是指部件库的存储方式,eplan支持两种方式即Microsoft Office access,Microsoft SQL Server,可以通过这两种方式打开部件库,如果要打开数 ...

  3. PROFIBUS,PROFINET,Ethernet三者的区别

    PROFIBUS,PROFINET,Ethernet三者的区别 简单一点说,PROFINET=PROFIbus+etherNET,把Profibus的主从结构移植到以太网上,所以profinet会有C ...

  4. 6.20 NOI 模拟

    \(T1\ left\ xor\ right\) 考虑把询问离线,查询变成 \([0,x-1]\) 的 \([l,r]\) 的区间和与 \([0,y]\) 的 \([l,r]\) 的区间和的差 考虑线 ...

  5. 学习ASP.NET Core Blazor编程系列一——综述

    一.NET 6概述 .NET 6 是微软统一.Net Core与.Net Framework 两大框架的第二个版本,微软在 .NET 5 中开始进行这两大框架的统一之路. .NET 6 将作为长期支持 ...

  6. Maven中使用ssm框架出现:org.apache.tomcat.util.modeler.BaseModelMBean.invoke 调用方法[manageApp]时发生异常

    org.apache.tomcat.util.modeler.BaseModelMBean.invoke 调用方法[manageApp]时发生异常 首先可以排查一下像: @RequestMapping ...

  7. 第九十六篇:恶补JS基础

    好家伙,来补基础啦,补JS的基础 先来一些概念性的东西 1.什么是JavaScript?  javaScript的简写形式就是JS,一种广泛用于客户端Web开发的脚本语言,常用来给HTML网页添加动态 ...

  8. 【Traefik二次开发】中间件 Middleware 开发

    本篇只讨论HTTP中间件 中间件定义 https://doc.traefik.io/traefik/middlewares/overview/ Attached to the routers, pie ...

  9. 从零教你使用MindStudio进行Pytorch离线推理全流程

    摘要:MindStudio的是一套基于华为自研昇腾AI处理器开发的AI全栈开发工具平台,该IDE上功能很多,涵盖面广,可以进行包括网络模型训练.移植.应用开发.推理运行及自定义算子开发等多种任务. 本 ...

  10. 使用plsql_plprofiler 分析过程块的执行

    前言:存储过程可能涉及很多的SQL及控制块,我们看到的执行时间是整个过程块的执行时间,如果我们认为性能有问题,我们只能逐条SQL的分析,查找问题SQL,效率非常低下.KingbaseES 提供了 pl ...