SpringBoot异步任务

一、注解实现

@EnableAsync注解

创建一个配置类,并在类上添加@EnableAsync注解,用来启用异步支持。

@Configuration
@EnableAsync
public class AsyncConfig {
}

或者,在启动类上添加@EnableAsync注解,用来启用异步支持。

@EnableAsync
@SpringBootApplication
public class SpringbootSampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootSampleApplication.class, args);
    }
}

异步任务类

创建一个包含异步方法的类,并在方法上添加@Async注解。

@Service
public class MyAsyncService {
    // 默认线程池
    @Async
    public void asyncTask() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 异步执行的任务逻辑
        System.out.println("异步任务正在执行");
    }

    public void task() {
        // 同步执行的任务逻辑
        System.out.println("其他任务正在执行");
    }
}

调用异步方法

asyncTask方法将在一个单独的线程中异步执行,而主线程将继续执行其他任务。

确保项目中添加了spring-boot-starter-async依赖,这样异步任务的支持才能生效。

注意:异步方法 和 调用方法 不能在同一个类中。

@RestController
@RequestMapping("/api")
public class MyController {

    @Autowired
    private MyAsyncService myAsyncService;

    @GetMapping("/asyncTask")
    public String asyncTask() {
        long start = System.currentTimeMillis();

        // 调用异步方法
        myAsyncService.asyncTask();

        // 主线程的其他逻辑
        myAsyncService.task();

        System.out.println("方法结束,执行耗时:" + (System.currentTimeMillis() - start));
        return "OK";
    }
}

对比

使用@Async注解,主线程马上返回,异步任务继续执行。
在这里插入图片描述

输出:
其他任务正在执行
方法结束,执行耗时:0
异步任务正在执行

不使用@Async注解,主线程方法全部同步执行。
在这里插入图片描述

输出:
异步任务正在执行
其他任务正在执行
方法结束,执行耗时:5015

使用自定义线程池

配置类中创建自定义线程池。

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean(name = "customTaskExecutor")
    public TaskExecutor customTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setThreadNamePrefix("CustomThread-");
        // CPU密集型:corePoolSize = CPU核数 + 1;IO密集型:corePoolSize = CPU核数 * 2
        int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
        executor.setCorePoolSize(corePoolSize); // 核心线程数目
        executor.setMaxPoolSize(corePoolSize); // 最大线程数
        executor.setKeepAliveSeconds(30); // 线程空闲后的最大存活时间
        executor.setQueueCapacity(100); // 阻塞队列大小,当核心线程使用满时,新的线程会放进队列
        // 线程执行的拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

在异步服务类上,使用@Async注解并指定value属性为自定义线程池的名字。

@Service
public class MyAsyncService {

    // 不指定则使用默认线程池
    @Async("customTaskExecutor")
    public void asyncTask() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 异步执行的任务逻辑
        System.out.println("异步任务正在执行");
    }
}

asyncTask方法将在名为customTaskExecutor的自定义线程池中执行。

确保异步任务调用方仍然使用@Autowired注解注入MyAsyncService,Spring Boot会自动关联使用相应的自定义线程池执行异步任务。

二、CompletableFuture实现

异步任务类

CompletableFuture是Java 8引入的一种异步编程的方式,它提供了更为灵活和强大的异步操作支持。

@Service
public class MyAsyncService {
	// 线程池,也可以使用自定义的线程池
    private final Executor customExecutor = Executors.newFixedThreadPool(5);

    public CompletableFuture<Void> performAsyncTask() {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // 异步执行的任务逻辑
            System.out.println("异步任务正在执行");
        }, customExecutor);
    }
}

在这个例子中,performAsyncTask方法返回了一个CompletableFuture<Void>,这表示异步任务没有返回值。CompletableFuture.runAsync(...)方法接受一个Runnable作为参数,并使用customExecutor作为执行器执行异步任务。

调用异步方法

@RestController
@RequestMapping("/api")
public class MyController {

    @Autowired
    private MyAsyncService myAsyncService;

    @GetMapping("/triggerAsyncTask")
    public String triggerAsyncTask() throws ExecutionException, InterruptedException {
        // 调用异步方法
        myAsyncService.performAsyncTask().get();

        // 主线程的其他逻辑
        return "OK";
    }
}

在Controller中,可以通过CompletableFuture.get()方法来等待异步任务的完成。

需要注意的是,get()方法会阻塞,等待到异步方法执行完成,且get()方法可能会抛出InterruptedExceptionExecutionException异常,因此需要进行适当的异常处理。

使用CompletableFuture的好处在于,你可以在异步任务中进行更复杂的操作,例如处理异步任务的结果、合并多个异步任务等。

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

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

相关文章

Linux(二)

远程登录 Linux大多应用于服务器&#xff0c;而服务器不可能像PC一样放在办公室&#xff0c;它们是放在IDC机房的&#xff0c;所以我平时登录linux系统都是通过远程登录的。 Linux系统中是通过ssh服务实现的远程登录功能。默认ssh服务开启了22端口&#xff0c;而且当我们安装…

docker elasticsearch8启动失败

docker elasticsearch8.12.0启动后提示这个&#xff0c;并且始终无法访问localhost:9200 received plaintext http traffic on an https channel, closing connection Netty4HttpChannel 解决方案&#xff1a;重新创建 elasticsearch容器&#xff0c;加上 -e xpack.security.…

scikit-learn 1.3.X 版本 bug - F1 分数计算错误

如果您正在使用 scikit-learn 1.3.X 版本&#xff0c;在使用 f1_score() 或 classification_report() 函数时&#xff0c;如果参数设置为 zero_division1.0 或 zero_divisionnp.nan&#xff0c;那么函数的输出结果可能会出错。错误的范围可能高达 100%&#xff0c;具体取决于数…

ArcGIS学习(三)数据可视化

ArcGIS学习(三)数据可视化 1.矢量数据可视化 需要提前说明的是,在ArcGIS中,所有的可视化选项设置都是在“图层属性”对话框里面的“符号系统”中实现的。 对于矢量数据的可视化,主要有四种可视化方式: 按“要素”可视化按“类别”可视化按“数量”可视化按“图表”可视…

Leetcode—38. 外观数列【中等】

2024每日刷题&#xff08;111&#xff09; Leetcode—38. 外观数列 实现代码 class Solution { public:string countAndSay(int n) {string ans "1";while(--n) {string next;for(int i 0; i < ans.size(); i) {int cnt 1;char c ans[i];while(i 1 < an…

PyTorch 2.2 中文官方教程(十七)

&#xff08;Beta&#xff09;使用缩放点积注意力&#xff08;SDPA&#xff09;实现高性能 Transformer 原文&#xff1a;pytorch.org/tutorials/intermediate/scaled_dot_product_attention_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 注意 点击这…

动态颗粒背景,适合VUE、HTML前端显示

动态颗粒背景&#xff0c;适合做背景使用&#xff0c;VUE、HTML前端显示直接看效果 废话不多说直接上代码&#xff1b; 一、html 代码部分 <template><div id"login"><div class"container"><div class"login-form"&g…

QXlsx Qt操作excel(1)

QXlsx 是一个用于处理Excel文件的开源C库。它允许你在你的C应用程序中读取和写入Microsoft Excel文件&#xff08;.xlsx格式&#xff09;。该库支持多种操作&#xff0c;包括创建新的工作簿、读取和写入单元格数据、格式化单元格、以及其他与Excel文件相关的功能。 关于QXlsx的…

Open CASCADE学习|拉伸

目录 1、沿方向拉伸 2、沿路径拉伸 3、变形拉伸 1、沿方向拉伸 #include <Geom_CylindricalSurface.hxx> #include <gp_Ax3.hxx> #include <GeomAPI_Interpolate.hxx> #include <BRepAdaptor_Curve.hxx> #include <BRepBuilderAPI_MakeEdge.hxx&…

Kubernetes基础(十一)-CNI网络插件用法和对比

1 CNI概述 1.1 什么是CNI&#xff1f; Kubernetes 本身并没有实现自己的容器网络&#xff0c;而是借助 CNI 标准&#xff0c;通过插件化的方式来集成各种网络插件&#xff0c;实现集群内部网络相互通信。 CNI&#xff08;Container Network Interface&#xff0c;容器网络的…

Docker 可视化工具

1、Portainer 概念介绍 Portainer是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用于方便地管理Docker环境&#xff0c;包括单机环境和集群环境。 Portainer分为开源社区版&#xff08;CE版&#xff09;和商用版&#xff08;BE版/EE版&#xff09;。 Porta…

【动态规划】【树形dp】【C++算法】968监控二叉树

作者推荐 【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数 本文涉及知识点 动态规划汇总 LeetCode:968监控二叉树 给定一个二叉树&#xff0c;我们在树的节点上安装摄像头。 节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。 计算监控树的所…

16.docker删除redis缓存数据、redis常用基本命令

1.进入redis容器内部 &#xff08;1&#xff09;筛选过滤出redis容器 docker ps | grep "redis"&#xff08;2&#xff09;进入redis容器 #说明&#xff1a;d24为redis容器iddocker exec -it d24 /bin/bash2.登陆redis (1) 进入redis命令行界面 redis-cli说明&a…

elastic-job VS xxl-job

1、Elastic-job介绍 Elastic-job 是由当当网基于quartz 二次开发之后的分布式调度解决方案 &#xff0c; 由两个相对独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成 。Elastic-Job-Lite定位为轻量级无中心化解决方案&#xff0c;使用jar包的形式提供分布式任务的协调服务…

day20网页基本标签

网页基本标签 标题标签段落标签换行标签水平线标签字体样式标签注释和特殊符号 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>网页基本标签</title> </head> <body> <!--标题…

matlab使用jdbc连接数据库

1、打包jdbc 2、在matlab安装目录下&#xff0c;进去toolbox目录下&#xff0c;新建一个对应放jdbc包的文件夹&#xff0c;加入放入的是mysql的jdbc驱动包&#xff0c;就新建一个mysql目录&#xff0c;将驱动包放入mysql目录下 3、在toolbox目录下&#xff0c;找到local目录&a…

DVI接口主机连接VGA显示器解决方案:DVI转VGA转换器DV

DVI转VGA转换器概述 DVI转VGA转换器能够将DVI数字信号转换成VGA模拟信号&#xff0c;通过VGA线缆传输给VGA显示设备使用&#xff0c;这样就能实现DVI接口主机连接VGA接口的显示器。 DVI转VGA转换器DV DVI转VGA转换器DV接口说明 DVI转VGA转换器DV接口介绍 DVI转VGA转换器连接示…

对象内存与方法调用机制

对象的内存布局 对象、字符串和数组都是引用类型&#xff0c;指向的数 我们以下面main方法部分代码片段为例&#xff1a; Cat cat new Cat(); cat.name "小白"; cat.age 12; cat.color "白色"; 首先执行mian方法&#xff0c;会在栈里创建一个独立的m…

PMP资料怎么学?PMP备考经验分享

PMP考试前大家大多都是提前备考个一两个月&#xff0c;但是有些朋友喜欢“不走寻常路”&#xff0c;并不打算去考PMP认证&#xff0c;想要单纯了解PMP&#xff0c;不管要不要考证&#xff0c;即使是仅仅学习了解一下我个人都非常支持&#xff0c;因为专业的基础的确能提高工作效…

基恩士 KV-8000 PLC通讯简单测试

1、KV-8000通讯协议 基恩士 KV-8000 PLC支持多种通讯方式&#xff0c;包括&#xff1a;OPC UA、Modbus、上位链路命令等。其中OPC UA需要对服务器和全局变量进行设置&#xff0c;Modbus需要调用功能块。默认支持的是上位链路命令&#xff0c;实际是一条条以回车换行结束的ASCII…