ThreadPoolTaskExecutor自定义线程池的配置和使用,队列中的不属于exe
分享于 点击 42217 次 点评:175
ThreadPoolTaskExecutor自定义线程池的配置和使用,队列中的不属于exe
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(); } }
- 使用jmeter压测异步接口
- RestTemplate可进行池化,提高性能。可参考:https://www.cnblogs.com/xietingwei/p/17558473.html
用户点评