ThreadPoolTaskExecutor自定义线程池的配置和使用

发布时间 2023-07-16 21:21:27作者: xietingweia
ThreadPoolTaskExecutor自定义线程池的配置和使用
  • 线程池ThreadPoolTaskExecutor和ThreadPoolExecutor的区别

    • ThreadPoolExecutor,这个类是JDK中的线程池类,继承自Executor,里面有一个execute()方法,用来执行线程,线程池主要提供一个线程队列,队列中保存着所有等待状态的线程,避免了创建与销毁的额外开销
  • ThreadPoolTaskExecutor,是Spring提供的线程池类

    • Spring异步线程池的接口类是TaskExecutor,本质还是java.util.concurrent.Executor
  • 准备工作

    • 启动类添加@EnableAsync

    • 需要异步的方法添加@Async("[线程池名]")

  • 自定义线程池

    /**
     * 自定义线程池
     * corePoolSize:当线程数小于corePoolSize个的时候,正常创建线程
     *
     * queueCapacity:当线程大于corePoolSize个的时候,将线程放入queueCapacity大小的队列
     *
     * maxPoolSize:当queueCapacity队列已满,将会继续创建线程,直到线程数超过maxPoolSize的大小,将抛出异常
     */
    @Configuration
    @EnableAsync
    public class ThreadPoolTaskConfig {
    	// 连接池名
        @Bean("threadPoolTaskExecutor")
        public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            //线程池创建的核心线程数,线程池维护线程的最少数量,即使没有任务需要执行,也会一直存活
            //如果设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭
            executor.setCorePoolSize(16);
    
            //队列容量(队列只存在任务,不存在线程)
            executor.setQueueCapacity(1024);
    
            //最大线程数;
            //当corePoolSize 以及queueCapacity 满了以后,会在线程中额外创建线程.最大线程数指的是当前存在的最大的线程数。队列中的不属于
            executor.setMaxPoolSize(64);
    
            //当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize
            //如果allowCoreThreadTimeout=true,则会直到线程数量=0
            executor.setKeepAliveSeconds(30);
            //优雅关闭
            executor.setWaitForTasksToCompleteOnShutdown(true);
    
            //线程名前缀
            executor.setThreadNamePrefix("自定义线程池-");
    
    
            //当线程数满MaxPoolSize时,可采用以下拒绝策略
            
            //CallerRunsPolicy():交由调用方线程运行,比如 main 线程;如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行
            //AbortPolicy():该策略是线程池的默认策略,如果线程池队列满了丢掉这个任务并且抛出RejectedExecutionException异常。
            //DiscardPolicy():如果线程池队列满了,会直接丢掉这个任务并且不会有任何异常
            //DiscardOldestPolicy():丢弃队列中最老的任务,队列满了,会将最早进入队列的任务删掉腾出空间,再尝试加入队列
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
    
            executor.initialize();
            return executor;
        }
    
    }
    
  • 连接线程池测试

    • 异步方法test (异步方法需要单独放在一个类中,该类需要注入IOC容器中)
    @Component
    @Slf4j
    public class TestComponent {
        @Autowired
        private RestTemplate restTemplate;
        
        @Async("threadPoolTaskExecutor")
        public void test(){
    
               long beginTime = CommonUtil.getCurrentTimestamp();
            ResponseEntity<String> forEntity = restTemplate.getForEntity("https://www.baidu.com/", String.class);
            String body = forEntity.getBody();
            long endTime = CommonUtil.getCurrentTimestamp();
            log.info("耗时={},body={}",endTime-beginTime,body);
        }
    }
    
    • 调用异步方法进行测试(测试接口与异步方法不能在同一个类中)
    @RestController
    @RequestMapping("/api")
    public class NotifyController {
    
        @Autowired
        private TestComponent testComponent;
        /**
         * 测试异步方法
         * @return
         */
        @RequestMapping("/test")
        public JsonData sendCode(){
        	testComponent.test();
            return JsonData.buildSuccess();
        }
    }