SpringBoot异步任务

一、注解实现

@EnableAsync注解

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

java 复制代码
@Configuration
@EnableAsync
public class AsyncConfig {
}

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

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

异步任务类

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

java 复制代码
@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依赖,这样异步任务的支持才能生效。

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

java 复制代码
@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

使用自定义线程池

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

java 复制代码
@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属性为自定义线程池的名字。

java 复制代码
@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引入的一种异步编程的方式,它提供了更为灵活和强大的异步操作支持。

java 复制代码
@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作为执行器执行异步任务。

调用异步方法

java 复制代码
@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的好处在于,你可以在异步任务中进行更复杂的操作,例如处理异步任务的结果、合并多个异步任务等。

相关推荐
苹果醋323 分钟前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader42 分钟前
深入解析 Apache APISIX
java·apache
盛派网络小助手1 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
菠萝蚊鸭1 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪1 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0071 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
∝请叫*我简单先生1 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl
ssr——ssss2 小时前
SSM-期末项目 - 基于SSM的宠物信息管理系统
java·ssm
一棵星2 小时前
Java模拟Mqtt客户端连接Mqtt Broker
java·开发语言
鲤籽鲲2 小时前
C# Random 随机数 全面解析
android·java·c#