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

相关推荐
小薛博客25 分钟前
22、Jenkins容器化部署Java应用
java·运维·jenkins
西贝爱学习29 分钟前
如何在 IntelliJ IDEA 中进行全局替换某个字段(或文本)
java·ide·intellij-idea
南部余额33 分钟前
Spring 基于注解的自动化事务
java·spring·自动化
alf_cee33 分钟前
通过Idea 阿里插件快速部署java jar包
java·ide·intellij-idea
努力的小郑34 分钟前
MySQL索引(三):字符串索引优化之前缀索引
后端·mysql·性能优化
坚持每天敲代码1 小时前
【教程】IDEA中导入springboot-maven工程
java·maven·intellij-idea
CodeCraft Studio1 小时前
国产化PDF处理控件Spire.PDF教程:如何在 Java 中通过模板生成 PDF
java·python·pdf·spire.pdf·java创建pdf·从html创建pdf
IT_陈寒1 小时前
🔥3分钟掌握JavaScript性能优化:从V8引擎原理到5个实战提速技巧
前端·人工智能·后端
阿方.9181 小时前
《数据结构全解析:栈(数组实现)》
java·开发语言·数据结构
YC运维1 小时前
Ansible题目全解析与答案
java·算法·ansible