SpringBoot 中异步任务实现及自定义线程池执行异步任务

3476 篇文章 106 订阅

在项目的开发中,异步任务是非常重要的一个点,在我们程序对一些处理较慢的情况,可以使用异步任务,直接响应前端结果,再异步处理任务。这也是提高用户体验的地方,不然会有可能用户需要等待很久。

一、模拟同步任务处理复杂逻辑

Service里通过线程休眠3s的方式模拟处理复杂的任务

然后在Controller中调用这个服务,之后返回前端ok

在前端调用的时候就会一直处于加载状态,3s后才会返回响应的结果,这就是同步任务,我们想要先返回ok,然后Service的处理逻辑异步去执行。

二、异步任务的使用

1. 在启动类中加入@EnableAsync注解,表明开启异步功能

java复制代码import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync // 开启异步功能
public class MySpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApplication.class, args);
    }
}

2. 在对应的Service方法上添加@Async注解

java复制代码import com.jk.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncServiceImpl implements AsyncService {
    @Override
    @Async // 设置方法为异步任务
    public void test() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("数据处理完毕");
    }
}

这样就实现了我们异步任务的使用,此时再调用这个接口,就会立即返回ok,然后程序异步去执行数据处理的任务。

在上面这种方法可以实现基本的异步任务,其实本质也是SpringBoot使用线程池的方式去处理任务,对于这个默认线程池的配置,我们可以在application.yml中进行配置

yml复制代码# 线程池配置参数
task:
  pool:
    corePoolSize: 10 # 设置核心线程数
    maxPoolSize: 20  # 设置最大线程数
    keepAliveTime: 300 # 设置空闲线程存活时间(秒)
    queueCapacity: 100 # 设置队列容量
    threadNamePrefix: "async-" # 设置线程名称前缀
    awaitTerminationSeconds: 60 #  设置线程池等待终止时间(秒)

但是对于我们项目开发中,如果有多个异步任务,每个异步任务需要调度的系统资源不一样,如支付我们可能需要调用较多的系统资源去异步处理,而邮件发送不需要太多的系统资源处理,这时候我们就可以自定义两个线程池来分别去异步处理这两个任务。

三、自定义线程池配置及使用

1. 创建自定义线程池配置类

config.AsyncConfig:

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

@Configuration
@EnableAsync
public class AsyncConfig {
    @Bean("asyncExecutor")
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(10);
        // 最大线程数
        executor.setMaxPoolSize(20);
        // 任务队列大小
        executor.setQueueCapacity(100);
        // 线程池名称前缀
        executor.setThreadNamePrefix("custom-async-");
        // 允许线程的空闲时间
        executor.setKeepAliveSeconds(30);
        /**
         * 拒绝处理策略
         * CallerRunsPolicy():交由调用方线程运行,比如 main 线程。
         * AbortPolicy():直接抛出异常。
         * DiscardPolicy():直接丢弃。
         * DiscardOldestPolicy():丢弃队列中最老的任务。
         */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 线程初始化
        executor.initialize();
        return executor;
    }
}

因为@Configuration会自动注入到SpringBoot容器里,所以我们可以把@EnableAsync写在这里不需要再写在启动类上,另外通过@Bean的方式把这个线程池对象注入到容器

2. 在相应的Service方法上通过@Async指定线程池执行

java复制代码import com.jk.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncServiceImpl implements AsyncService {
    @Override
    @Async("asyncExecutor") // 需要指定自定义线程池的名称
    public void test() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("数据处理完毕");
    }
}

这样就实现了我们自定义线程池执行异步任务,如果需要多个线程池,我们同样可以在线程池配置类中定义多个,如下所示,然后在相应的Service方法上指定线程池名称即可。

这样就实现了在SpringBoot中使用异步任务及配置自定义线程池去执行异步任务

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值