SpringBoot 异步任务处理

简介: SpringBoot 异步任务处理

SpringBoot配置异步任务

有些业务是不需要你同步去操作的, 例如: 适用于处理log、发送邮件、短信……等

我们不能因为短信没发出去而没有执行接下来的业务逻辑, 这个时候我们就应该去把这些耗时的任务弄成异步的

  • 首先要在启动类里面增加如下注解
@EnableAsync
  • 定义异步任务类并使用@Component标记组件被容器扫描,异步方法加上@Async

如果整个类的操作都是异步的话 @Async 可以给类加上, 要把异步任务封装到类里面,不能直接写到Controller

  • TestTaskController.java
package com.cj.tool.comtool.controller;
import com.cj.tool.comtool.task.AsyncTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestTaskController {
    @Autowired
    private AsyncTask asyncTask;
    // 直接调起异步任务。正常执行肯定是堵塞的
    @GetMapping("/api/v1/test_task")
    public long testTask() throws InterruptedException {
        long begin = System.currentTimeMillis();
        asyncTask.task1();
        asyncTask.task2();
        asyncTask.task3();
        long end = System.currentTimeMillis();
        System.out.println("Controller 执行时间" + (end - begin));
        return end - begin;
    }
}
  • AsyncTask.java
package com.cj.tool.comtool.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
@Async
public class AsyncTask {
    public void task1() throws InterruptedException {
        long begin = System.currentTimeMillis();
        Thread.sleep(1000);
        long end = System.currentTimeMillis();
        System.out.println("task1耗时:"+ (end - begin));
    }
    public void task2() throws InterruptedException {
        long begin = System.currentTimeMillis();
        Thread.sleep(2000);
        long end = System.currentTimeMillis();
        System.out.println("task2耗时:"+ (end - begin));
    }
    public void task3() throws InterruptedException {
        long begin = System.currentTimeMillis();
        Thread.sleep(3000);
        long end = System.currentTimeMillis();
        System.out.println("task3耗时:"+ (end - begin));
    }
}

可以看到在AsyncTask里面都是有sleep的, 但是我们使用了异步


Controller执行时间 是先输出的, 我们的任务去开另外的线程执行, 这样大大增加了我们的程序效率, 在项目里面合适使用异步任务, 可以大大提高我们的QPS

获取异步返回数据

上面例子虽然解决了堵塞的问题, 但是有的时候我们希望获取异步任务的返回结果, 再进行后续工作。放心 这个也有方案

添加异步返回任务

  • AsyncTask.java
public Future<String> task4() throws InterruptedException {
        long begin = System.currentTimeMillis();
        Thread.sleep(4000);
        long end = System.currentTimeMillis();
        System.out.println("task4耗时:"+ (end - begin));
        return new AsyncResult<>("Task4的数据");
    }
    public Future<Integer> task5() throws InterruptedException {
        long begin = System.currentTimeMillis();
        Thread.sleep(5000);
        long end = System.currentTimeMillis();
        System.out.println("task5耗时:"+ (end - begin));
        return new AsyncResult<>(123);
    }
    public Future<String> task6() throws InterruptedException {
        long begin = System.currentTimeMillis();
        Thread.sleep(6000);
        long end = System.currentTimeMillis();
        System.out.println("task6耗时:"+ (end - begin));
        return new AsyncResult<>("Task6的数据");
    }
  • TestTaskController.java
@GetMapping("/api/v1/test_task")
    public long testTask() throws InterruptedException, ExecutionException {
        long begin = System.currentTimeMillis();
//        asyncTask.task1();
//        asyncTask.task2();
//        asyncTask.task3();
        Future<String> task4Result = asyncTask.task4();
        Future<Integer> task5Result = asyncTask.task5();
        Future<String> task6Result = asyncTask.task6();
        // 等每个任务执行完了就跳出
        for (;;) {
            if (task4Result.isDone() && task5Result.isDone() && task6Result.isDone()) {
                break;
            }
        }
        // 获取返回结果
        String task4res = task4Result.get();
        int task5res = task5Result.get();
        System.out.println(task4res);
        System.out.println(task5res);
        long end = System.currentTimeMillis();
        System.out.println("Controller 执行时间" + (end - begin));
        return end - begin;
    }

说一下流程

1)增加Future<String> 返回结果需呀 new AsyncResult<String>("task执行完成");


2)如果需要拿到结果 需要判断全部的 task.isDone(), 然后再task.get() 获取返回数据

  • 效果


可以看到 还是异步的, 最长耗时6000, 这样就可以应对不同的业务了, 如果是同步的话肯定需要 15000

本文为作者原创,手码不易,允许转载,转载后请以链接形式说明文章出处。

目录
相关文章
|
2月前
|
druid Java 数据库
Spring Boot的定时任务与异步任务
Spring Boot的定时任务与异步任务
|
4天前
|
监控 Java API
Spring Boot与异步任务:整合与应用场景
【4月更文挑战第29天】异步任务在现代应用程序开发中扮演着重要的角色,它们可以提高应用程序的性能和响应速度,尤其适用于处理长时间运行的任务或需要等待外部资源的场景。Spring Boot提供了强大的支持来简化异步任务的实现。
15 0
|
15天前
|
Java API 调度
springboot的异步类的介绍
【4月更文挑战第18天】FutureTask 是 Java 并发 API 中的一个实用类,它实现了 Future 接口并扩展了 Runnable,因此它可以被 ExecutorService 执行。FutureTask 通常用于包装 Callable 或 Runnable 对象,这样它们就可以提交给 ExecutorService 并获得 Future 对象,用于查询计算的状态和结果
15 1
|
1月前
|
Java Spring
SpringBoot+async异步调用接口以及几个任务同时完成和异步接口实现和调用
SpringBoot+async异步调用接口以及几个任务同时完成和异步接口实现和调用
24 0
|
2月前
|
JavaScript Java API
spring boot使用异步多线程
一文讲清楚spring boot如何结合异步多线程实现文件的导出这类耗时间的操作优化以及常用的场景,了解异步思想
31 0
spring boot使用异步多线程
|
4月前
|
SQL 分布式计算 Java
SpringBoot集成quartz调度linkis任务
SpringBoot集成quartz调度linkis任务
|
4月前
|
Java 调度 流计算
在使用Spring Boot启动Flink处理任务时
在使用Spring Boot启动Flink处理任务时【1月更文挑战第22天】【1月更文挑战第108篇】
56 1
|
5月前
|
Java
Springboot整合Activity7:任务,历史任务,UEL表达式(三)
Springboot整合Activity7:任务,历史任务,UEL表达式(三)
|
5月前
|
Java
Springboot整合Activity7:任务,历史任务,UEL表达式(二)
Springboot整合Activity7:任务,历史任务,UEL表达式(二)
|
5月前
|
消息中间件 Java 中间件
Spring Boot异步消息之AMQP讲解及实战(附源码)
Spring Boot异步消息之AMQP讲解及实战(附源码)
97 1