Spring boot配置线程池

1,265 阅读2分钟

一、初始化线程池

@Configuration
@EnableAsync
@Slf4j
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setKeepAliveSeconds(1000);// 空闲时间
        taskExecutor.setCorePoolSize(5);// 线程池大小
        taskExecutor.setMaxPoolSize(5);// 线程池最大线程数
        taskExecutor.setQueueCapacity(0);// 最大等待任务数
        taskExecutor.setThreadNamePrefix("thread-pool-");//前缀
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //拒绝策略
        taskExecutor.initialize();
        return taskExecutor;
    }


    /**
     * 自定义异常处理
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new MyAsyncExceptionHandler();
    }

    static class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
            String methodName = method.getName();
            log.info("当前异常方法名,{}" , methodName);
        }
    }
}

二、配置说明

  • corePoolSize 线程池维护线程的最少数量
  • keepAliveSeconds 线程池维护线程所允许的空闲时间
  • maxPoolSize 线程池维护线程的最大数量
  • queueCapacity 线程池所使用的缓冲队列

当一个任务通过execute(Runnable)方法欲添加到线程池时:

  • 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
  • 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列。
  • 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
  • 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
  • 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

默认的四种拒绝策略:

  • .AbortPolicy:默认拒绝策略,ThreadPoolExecutor中直接抛出异常不处理。
  • CallerRunsPolicy:在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务。(哪个线程创建了线程池,这个线程来执行被拒绝的任务)
  • DiscardPolicy:采用这个拒绝策略,会让被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。
  • DiscardOldestPolicy:策略的作用是,当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。

三、创建异步任务类

  1. 创建异步任务类
@Slf4j
@Service("asyncService")
public class AsyncService {
    @Async
    public void executorAsyncTask(String name){
        log.info("执行异步:{}" ,name);
    }
}