SpringBoot配置异步线程池
异步线程配置:
package com.micro.tiger.util; import java.util.concurrent.ThreadPoolExecutor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * 整合异步线程池 * @author 杏仁拌饭 * @date 201902201 * @description 线程池配置类 * */ @Configuration @EnableAsync public class ThreadPoolConfig { ThreadPoolTaskExecutor executor; @Value("${spring.threadPool.coreSize}") private int coreSize; @Value("${spring.threadPool.maxSize}") private int maxSize; @Value("${spring.threadPool.queueCapacity}") private int queueCapacity; @Value("${spring.threadPool.keepAliveSeconds}") private int keepAliveSeconds; @Bean ThreadPoolTaskExecutor taskExecutor(){ if(executor == null){ synchronized(ThreadPoolConfig.class){ if(executor == null){ executor = new ThreadPoolTaskExecutor(); // 核心线程数 executor.setCorePoolSize(coreSize); // 核心线程数 executor.setMaxPoolSize(maxSize); // 设置队列容量 executor.setQueueCapacity(queueCapacity); // 设置线程活跃时间(秒) executor.setKeepAliveSeconds(keepAliveSeconds); // 设置默认线程名称 executor.setThreadNamePrefix("ks-member-"); // 设置拒绝策略rejection-policy:当pool已经达到max size的时候,如何处理新任务 CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown(true); //线程池关闭时间-慎用(60S之后不管子任务有没有执行完毕,都要关闭线程池) executor.setAwaitTerminationSeconds(60); } } } return executor; } }
Service层配置异步线程执行方法:
@Service public class MakebookCommonServiceImpl implements MakebookCommonService { private static Logger logger = LoggerFactory.getLogger(MakebookCommonServiceImpl.class); //异步线程使用自定义线程池 @Async("taskExecutor") public void taskExecutorFile(final String filePath, final String fileName) throws InterruptedException { long time = 10000; Thread.sleep(time); logger.info("执行。。。{},fileName = {}", filePath, fileName); } }
controller调用方法:
@RestController public class MakebookeCommandProvider extends BaseProvider implements MakebookCommandFeignApi { @Autowired private MakebookCommonService makebookCommonService; @Override public BaseRsp<?> uploadFile(MultipartFile file) { try { //调用异步线程 makebookCommonService.taskExecutorFile(fileSavePath, fileName); return BaseRsp.returnSuccss(); } catch (Exception e) { throw new CommonException("上传文件异常,原因:", e); } } }
有些资料说需要在启动类中添加@EnableAsync注解开启异步线程,但是我在 1.5.19.RELEASE 版本中未使用此注解开启,也可以正常使用
遇到问题:
在service层配置私有方法(@Async注解过)从service层吊起,但是启动之后异步线程没有生效。
原因:
因为这个方法循环调用的,当在其他类中调用这个方法,每一次的循环都会创建这个对象,所以,每一次的创建和调用都是在一个独立的线程中进行的;如果是在当前对象中调用这个方法,那么在调用这个方法之前这个对象已经被创建了,所以结果就这样了。
当然,这个是一个很低级的错误,多线程的基础,但是有的时候就容易踩到这个坑
参考:https://blog.csdn.net/winter_chen001/article/details/81100284