异步线程池(SpringBoot)

本文介绍了如何在Spring3及后续版本中使用@Async注解实现异步方法调用,包括配置异步线程池、线程池参数设置以及注意事项,如方法可见性、注解使用限制等。
摘要由CSDN通过智能技术生成

如何使用

对于异步方法调用,从Spring3开始提供了@Async注解,我们只需要在方法上标注此注解,此方法即可实现异步调用。
当然,我们还需要一个配置类,通过Enable模块驱动注解@EnableAsync来开启异步功能。

线程池配置类

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 异步线程池配置
 */
@Slf4j
@Configuration
@EnableAsync//此注解也可以放在启动类
public class AsyncThreadPoolConfig implements AsyncConfigurer {

    @Bean(name = "asyncExecutor")
    public ThreadPoolTaskExecutor asyncThreadPoolTaskExecutor(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        //核心线程数
        threadPoolTaskExecutor.setCorePoolSize(20);
        //最大线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        threadPoolTaskExecutor.setMaxPoolSize(100);
        //缓存队列
        threadPoolTaskExecutor.setQueueCapacity(50);
        //线程空闲时间,当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        threadPoolTaskExecutor.setKeepAliveSeconds(200);
        //异步方法内部线程名称
        threadPoolTaskExecutor.setThreadNamePrefix("async-");

        /**
         * 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略
         * 通常有以下四种策略:
         * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
         * ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
         * ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
         * ThreadPoolExecutor.CallerRunsPolicy:重试添加当前的任务,自动重复调用 execute() 方法,直到成功
         */
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    /**
     * 指定默认线程池,使用@Async注解时,不指定线程池名称,默认使用此线程池
     */
    @Override
    public Executor getAsyncExecutor() {
        return asyncThreadPoolTaskExecutor();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return ((ex, method, params) -> log.error("线程池执行任务发送时出现异常,执行方法为:{}",method.getName()));
    }
}

异步方法调用

错误示范:同步方法methodA中调用异步方法methodB

@Service
public class UserServiceImpl implements UserService {
    public User methodA(User user){
        System.out.println("执行task1......");
        methodB(user);
        return user;
    }

    @Async
    public void methodB(User user) {
        System.out.println("异步执行task2......");
    }
}

*正确使用:*

@RestController
@RequestMapping("/user")
public class UserController(@RequestBody User user){
    @Autowired
    private UserService userService;
	userService.methodA();
	userService.methodB();
}
@Service
public class UserServiceImpl implements UserService {
    public User methodA(User user){
        System.out.println("执行task1......")
        return user;
    }

    @Async
    public void methodB(User user) {
        System.out.println("异步执行task2......");
    }
}

注意事项

@Async失效的几个原因:

1.注解@Async的方法不是public方法;
2.方法不是void或者Future
3.未加@EnableAsync注解;
4.注解@Async方法使用static修饰会失效;
5.调用方和使用@Async的方法不能在同一个类中;
6.在@Async的方法上使用@Transactional是起不到作用的,但在调用其的方法上可以有效的使用。

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值