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

 

posted @ 2019-03-30 12:34  杏仁拌饭  阅读(238)  评论(0)    收藏  举报