SpringBoot项目使用自带的@Async异步处理功能实现业务逻辑的异步调用

SpringBoot项目使用自带的@Async异步处理功能实现业务逻辑的异步调用

物料准备:

1.配置启用SpringBoot内置的@EnableAsync功能

2.定义async任务执行需要的线程池配置

3.定义具体的async方法,可以是无返回值的void方法,也可以是有返回值的方法

在启动类上配置@EnableAsync

也可以单独写个@Configuration配置类,在上面加@EnableAsync注解。但是实际开发常常直接配置到app启动类上

@SpringBootApplication
@EnableAsync //启用 SpringBoot内置的Async功能
public class KnowWikiBackendApplication {
    public static void main(String[] args) {
        SpringApplication.run(KnowWikiBackendApplication.class, args);
    }
}

自定义一个AsyncConfig类来配置async任务执行需要的线程池

@Configuration
public class AsyncConfig {
  @Bean("asyncCountTestTaskExecutor")
    public ThreadPoolTaskExecutor asyncCountTaskTest(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数5:线程池创建时候初始化的线程数
        executor.setCorePoolSize(5);
        //最大线程数10:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setMaxPoolSize(10);
        //缓冲队列100:用来缓冲执行任务的队列
        executor.setQueueCapacity(100);
        //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setKeepAliveSeconds(60);
        //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
        executor.setThreadNamePrefix("countTestTaskAsync-");
        //线程池满了后新任务由 任务发起者的线程执行
        RejectedExecutionHandler callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();
        executor.setRejectedExecutionHandler(callerRunsPolicy);
        executor.initialize();
        return executor;
    }
    
    @Bean("asyncVoidTestTaskExecutor")
    public ThreadPoolTaskExecutor asyncVoidTaskTest(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数5:线程池创建时候初始化的线程数
        executor.setCorePoolSize(5);
        //最大线程数10:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setMaxPoolSize(10);
        //缓冲队列100:用来缓冲执行任务的队列
        executor.setQueueCapacity(100);
        //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setKeepAliveSeconds(60);
        //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
        executor.setThreadNamePrefix("voidTestTaskAsync-");
        //线程池满了后新任务由 任务发起者的线程执行
        RejectedExecutionHandler callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();
        executor.setRejectedExecutionHandler(callerRunsPolicy);
        executor.initialize();
        return executor;
    }
}

自定义一个类AsyncAllService实现具体的async方法逻辑

@Service
@Slf4j
public class AsyncAllService {
   @Async("asyncCountTestTaskExecutor")
    public Future<Long> testCount1(){  //注意要使用Future接口包括起来返回的类型
        String now = DateUtil.now();
        log.info("now:{}",now);
        log.info("---exec testCount1------------");
        String input1 = "aweff2 eawf 3ww 3w5g ref 3w4gaerfg vq34efqgv3 qvg egv23rg aref 3aewe2r3 ewer2";
        String input2 = "w";
        String s1 = input1.toUpperCase();
        String s2 = input2.toUpperCase();
        //字符s2 出现的次数
        //把s1中的s2都替换成空后的字符串s3
        String s3 = s1.replaceAll(s2, "");
        //s1-s3的长度就是s2出现的次数
        long count = input1.length() - s3.length();
        return new AsyncResult<Long>(count); //这里使用 AsyncResult接收执行结束返回的值, AsyncResult是spring提供的一个异步返回值包装器, AsyncResult实现了jdk里的Future
    }

    @Async("asyncVoidTestTaskExecutor")
    public void testAsync2(){
        String now = DateUtil.now();
        log.info("now:{}",now);
        log.info("---exec testAsync2------------");
    }
}

在controller中写个API调用这2个异步任务

@Slf4j
@RestController
@RequestMapping("/third")
public class TestApi {
    @Autowired
    private AsyncAllService asyncAllService;

    @GetMapping("/t1")
    public String te() throws ExecutionException, InterruptedException {
        log.trace("trace---test!!!!!");
        log.info("info---test!!!!!");
        log.warn("warn---test!!!!!");
        log.debug("debug---test!!!!!");
        log.error("error---test!!!!!");
        //有返回值的async任务
        Future<Long> longFuture = asyncAllService.testCount1();
        //无返回值的async任务
        asyncAllService.testAsync2();
        //有返回值的async任务,需要多个future都执行后,最后统一get返回值
        Long l605 = longFuture.get();
        log.info("async task res:{}",l605);
        return "thirdTestApi测试!";
    }
}    

测试执行效果

2023-06-05 19:02:05,596  INFO [countTestTaskAsync-1] [f2ce98d2-10ed-490f-b773-06c07ecb86c8] c.a.k.a.b.AsyncAllService [AsyncAllService.java : 35] now:2023-06-05 19:02:05
2023-06-05 19:02:05,597  INFO [countTestTaskAsync-1] [f2ce98d2-10ed-490f-b773-06c07ecb86c8] c.a.k.a.b.AsyncAllService [AsyncAllService.java : 36] ---exec testCount1------------
2023-06-05 19:02:05,596  INFO [voidTestTaskAsync-1] [f2ce98d2-10ed-490f-b773-06c07ecb86c8] c.a.k.a.b.AsyncAllService [AsyncAllService.java : 53] now:2023-06-05 19:02:05
2023-06-05 19:02:05,599  INFO [voidTestTaskAsync-1] [f2ce98d2-10ed-490f-b773-06c07ecb86c8] c.a.k.a.b.AsyncAllService [AsyncAllService.java : 54] ---exec testAsync2------------

通过日志可以看到,2个异步方法 实现了并发执行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ThinkPet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值