【Java】SpringBoot中实现异步编程

前言

首先我们来看看在Spring中为什么要使用异步编程,它能解决什么问题?

什么是异步?

首先我们先来看看一个同步的用户注册例子,流程如下:
【Java】SpringBoot中实现异步编程_第1张图片

异步的方式如下:
【Java】SpringBoot中实现异步编程_第2张图片

在用户注册后将成功结果返回,使用异步的方式来赠送优惠券,接下来我们来看一下代码示例。

示例

第一步:新建配置类,开启@Async功能支持
使用@EnableAsync来开启异步任务支持,@EnableAsync注解可以直接放在SpringBoot启动类上,也可以单独放在其他配置类上。我们这里选择使用单独的配置类AsyncConfiguration

新建配置类AsyncConfiguration

@Configuration
@EnableAsync
public class AsyncConfiguration {
}

第二步:在方法上标记异步调用
增加一个Component类,用来进行业务处理,同时添加@Async注解,代表该方法为异步处理。

@Component
public class MemberServiceAsync {
    private static Logger logger = Logger.getLogger(MemberServiceAsync.class);
    @Async
    public void sendCoupons() {
        try {
            logger.info("发送优惠券");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

第三步:在Controller中进行异步方法调用

@RestController
public class MemberService {

    private static Logger logger = Logger.getLogger(MemberService.class);

    @Resource
    private MemberServiceAsync async;

    @RequestMapping("insertMember")
    public String insertMember() {
        logger.info("会员新增数据");
        async.sendCoupons();
        return "注册成功";
    }
}

访问该接口并查看控制台信息

[INFO ] 2023-03-09 19:52:04,433 method:com.mayikt.service.MemberService.insertMember(MemberService.java:19)
会员新增数据
[INFO ] 2023-03-09 19:52:04,439 method:com.mayikt.service.MemberService.insertMember(MemberService.java:21)
注册成功
[INFO ] 2023-03-09 19:52:04,446 method:com.mayikt.service.MemberServiceAsync.sendCoupons(MemberServiceAsync.java:25)
发送优惠券

通过日志可以看到:主线程不需要等待异步方法执行完成,减少了响应时间,提高了接口性能。

通过上面三步我们就可以在SpringBoot中欢乐的使用异步方法来提高我们接口性能了

线程池

为异步操作提供一个线程池,我们在配置类中加上代码

@Configuration
@EnableAsync
public class AsyncConfiguration {
    @Bean(name = "asyncPoolTaskExecutor")
    public ThreadPoolTaskExecutor executor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //核心线程数
        taskExecutor.setCorePoolSize(10);
        //线程池维护线程的最大数量,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        taskExecutor.setMaxPoolSize(100);
        //缓存队列
        taskExecutor.setQueueCapacity(50);
        //许的空闲时间,当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        taskExecutor.setKeepAliveSeconds(200);
        //异步方法内部线程名称
        taskExecutor.setThreadNamePrefix("async-");
        /**
         * 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略
         * 通常有以下四种策略:
         * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
         * ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
         * ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
         * ThreadPoolExecutor.CallerRunsPolicy:重试添加当前的任务,自动重复调用 execute() 方法,直到成功
         */
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }
}

在注解上指定bean的名称:@Async(“asyncPoolTaskExecutor”)就可以了

你可能感兴趣的:(java,spring,boot,spring)