【SpringBoot】21 @Async异步任务线程池的隔离

news/2024/11/15 3:22:28/

Git仓库

https://gitee.com/Lin_DH/system

介绍

线程池隔离:指一种通过为每个服务提供独立的线程池来隔离服务之间的资源和执行环境的做法。
为什么需要线程池隔离?

  • 资源隔离,每个服务都有独立的线程池,可以避免由于某个服务的异常或高负载导致整个系统的线程资源耗尽。
  • 性能隔离,通过线程池隔离,可以更好地控制每个服务的并发度和资源利用率,提高系统的性能和稳定性。
  • 故障隔离,当一个服务发生故障时,独立的线程池可以使故障不会传播到其他服务,从而增强系统的容错性。
    实现线程池隔离的方式
  • 使用线程池,为每个服务或功能模块创建独立的线程池。
  • 使用线程池隔离框架,如 Hystrix、Resilence4j 等容错框架,可以轻松实现线程池隔离以及其他容错机制。

实现代码

第一步:初始化多个线程池

TaskPoolConfig.java

java">package com.lm.system.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;/*** @author DUHAOLIN* @date 2024/10/17*/
@EnableAsync
@Configuration
public class TaskPoolConfig {@Beanpublic Executor taskExecutor1() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(2);executor.setMaxPoolSize(2);executor.setQueueCapacity(10);executor.setKeepAliveSeconds(60);executor.setThreadNamePrefix("executor-1-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}@Beanpublic Executor taskExecutor2() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(2);executor.setMaxPoolSize(2);executor.setQueueCapacity(10);executor.setKeepAliveSeconds(60);executor.setThreadNamePrefix("executor-2-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}}

第二步:创建异步回调任务,并指定要使用的线程池

AsyncCallBackTask_1.java

java">package com.lm.system.task;import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;import java.util.Random;
import java.util.concurrent.CompletableFuture;/*** 异步回调* @author DUHAOLIN* @date 2024/10/17*/
@Slf4j
@Component
public class AsyncCallBackTask_1 {public static Random random = new Random();@Async("taskExecutor1")public CompletableFuture<String> one(String taskNo) throws InterruptedException {log.info("开始执行任务:{}", taskNo);long startTime = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long endTime = System.currentTimeMillis();log.info("完成任务:{},耗时:{} 毫秒", taskNo, endTime - startTime);return CompletableFuture.completedFuture("任务执行完成");}@Async("taskExecutor2")public CompletableFuture<String> two(String taskNo) throws InterruptedException {log.info("开始执行任务:{}", taskNo);long startTime = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long endTime = System.currentTimeMillis();log.info("完成任务:{},耗时:{} 毫秒", taskNo, endTime - startTime);return CompletableFuture.completedFuture("任务执行完成");}}

第三步:测试类添加测试方法

SystemApplicationTests.java

java">@Slf4j
@SpringBootTest(classes = SystemApplication.class)
class SystemApplicationTests {@Resourceprivate AsyncCallBackTask_1 asyncCallBackTask_1;@Testpublic void asyncTaskPoolIsolation() throws InterruptedException { //测试线程池隔离long startTime = System.currentTimeMillis();//线程池1CompletableFuture<String> task_1 = asyncCallBackTask_1.one("task_1");CompletableFuture<String> task_2 = asyncCallBackTask_1.one("task_2");CompletableFuture<String> task_3 = asyncCallBackTask_1.one("task_3");//线程池2CompletableFuture<String> task_4 = asyncCallBackTask_1.two("task_4");CompletableFuture<String> task_5 = asyncCallBackTask_1.two("task_5");CompletableFuture<String> task_6 = asyncCallBackTask_1.two("task_6");CompletableFuture.allOf(task_1, task_2, task_3, task_4, task_5, task_6).join();long endTime = System.currentTimeMillis();log.info("任务执行完成,总耗时:" + (endTime - startTime) + "毫秒");}}

效果图

执行测试类 asyncTaskPoolIsolation 方法,得到如下结果:因为配置的初始化线程为2,taskExecutor1 会先执行 one 方法的前两个(图中的 task_2、task_1),task_3 进入缓存队列,等待前两个任务中的一个执行完就可以执行;taskExecutor2 也会先执行 two 方法的前两个(图中的 task_5、task_4),task_6 进入缓存队列,等待前两个任务中的一个执行完就可以执行。

项目结构图

在这里插入图片描述


http://www.ppmy.cn/news/1547112.html

相关文章

电商系统设计与实现:Spring Boot框架

6 系统测试 程序软件一旦被开发完成之后&#xff0c;在真正投入日常生活中进行运行使用之前&#xff0c;是必须要经历测试这一个重要的操作环节&#xff0c;因为开发期间注重的是每个单独功能模块的开发&#xff0c;尽管每次开发完成一个单独功能模块时&#xff0c;会通过单元测…

09C++结构体

/*结构体属于用户自定义的数据类型&#xff0c; 允许用户存储不同的数据类型, 语法:struct 结构体名{结构体成员列表} ;*/ //struct 结构体名 变量名 #include <iostream> #include <string> using namespace std; struct student { string name; int age;int s…

【网络】完美配置 HTTPS:优化 SSL/TLS 证书以增强网站安全和性能

目录 引言一、申请 SSL/TLS 证书1.1 什么是 SSL/TLS 证书&#xff1f;1.2 如何申请 SSL/TLS 证书&#xff1f;1.3 SSL 证书的种类 二、安装 SSL/TLS 证书2.1 Apache 安装 SSL 证书2.2 Nginx 安装 SSL 证书2.3 IIS 安装 SSL 证书2.4 测试 SSL 配置 三、强制使用 HTTPS3.1 设置 H…

管理Linux软件包和进程

管理Linux软件包和进程 1. 源码下载安装软件 1.1 概念 源码文件&#xff1a;程序编写者使用C或C等语言编写的原始代码文本文件源码文件使用.tar.gz或.tar.bz2打包成压缩文件 1.2 特点 源码包可移植性好&#xff0c;与待安装软件的工作环境依赖性不大由于有编译过程&#x…

普通电脑上安装属于自己的Llama 3 大模型和对话客户端

#大模型下载地址&#xff1a;# Llama3 因为Hugging Face官网正常无法访问&#xff0c;因此推荐国内镜像进行下载&#xff1a; 官网地址&#xff1a;https://huggingface.co 国内镜像&#xff1a;https://hf-mirror.com GGUF 模型文件名称接受&#xff0c;如上述列表中&…

golang go语言 组建微服务架构详解 - 代码基于开源框架grpc+nacos服务管理配置平台

整体介绍&#xff1a; 本文主要介绍如何用go语言 来组建微服务的框架&#xff0c;grpc服务管理 示例框架 代码由grpcnacos go sdk 组成。 grpc负责将调用序列化并传递到远端&#xff0c;nacos负责服务发现和服务管理。 grpc和nacos都是开源产品。代码复制下来就能跑。 微服…

Ubuntu20.04 安装build-essential问题

#sudo apt-get install build-essential问题 The following packages have unmet dependencies: build-essential : Depends: libc6-dev but it is not going to be installed or libc-dev Depends: g (> 4:9.2) but it is not going to be installed E: Unable to correct…

2024年11月6日Github流行趋势

项目名称&#xff1a;twenty 项目维护者&#xff1a;charlesBochet, lucasbordeau, Weiko, FelixMalfait, bosiraphael 项目介绍&#xff1a;正在构建一个由社区支持的现代版Salesforce替代方案。 项目star数&#xff1a;19,714 项目fork数&#xff1a;2,200 项目名称&#xf…