Springboot中ThreadPoolTaskExecutor、ScheduledThreadPoolExecutor和ThreadPoolTaskScheduler的区别和用法
刚开始看到这三个类,我看了很久也没看出它们的区别。先分别对其做个简短介绍。先介绍一下三个类的共性,都是为了对JVM资源进行合理分配,并用线程池的特性也实现。ThreadPoolTaskExecutor常用于项目中的异步任务处理,其UML关系如下:其配置如下:@Configuration@EnableAsyncpublic class AsyncConfiguration implements As
刚开始看到这三个类,我看了很久也没看出它们的区别。先分别对其做个简短介绍。
先介绍一下三个类的共性,都是为了对JVM资源进行合理分配,并用线程池的特性也实现。
ThreadPoolTaskExecutor常用于项目中的异步任务处理,其UML关系如下:
其配置如下:
@Configuration @EnableAsync public class AsyncConfiguration implements AsyncConfigurer{ @Override public Executor getAsyncExecutor(){ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(15); executor.setThreadNamePrefix("DailyBackup-"); executor.initialize(); return executor; } }
项目用法为:
@Service @Async public class AsyncServiceImpl { public void test(int i){ try { System.out.println(i+"start"); Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i+"end"); } }
最后和普通的service用法一样,需要使用的时候注入IOC容器即可。这样就可以使用线程池的方式开启异步任务,简化多线程启动的同时,避免了系统资源的无序消耗。
ScheduledThreadPoolExecutor 常用于项目中的异步任务处理,其UML关系如下:
其配置如下:
@Configuration public class ScheduledConfiguration{ @Bean public ScheduledThreadPoolExecutor scheduledThreadPoolExecutor(){ return new ScheduledThreadPoolExecutor(5); } }
项目用法,在需要用到的地方直接注入即可。其在可以满足异步线程的同时,还可以满足延时执行任务,循环执行任务,常用方法有
scheduleAtFixedRate,scheduleWithFixedDelay
。其实从名字可以看出来,它首先是一个Executor的角色,之后再配置了一定的Scheduled定时执行任务的功能。
最后是 ThreadPoolTaskScheduler常用于项目中的带有定时计划的异步任务处理,其UML关系如下:
其使用可以直接从IOC容器获取:
@Autowired private ThreadPoolTaskScheduler threadPoolTaskScheduler;
但是由于其的主要任务是满足定时任务的需求,所以使用这个类的同时要在配置类,或者启动类加上@EnableScheduling注解,不然启动会报错。
有人会说,我们通常知道的@EnableScheduling注解和@Scheduled一起使用,就可以构造定时任务,为什么要引如这个ThreadPoolTaskScheduler来执行定时任务,其实归根结底,也是为了避免后期项目需求扩张以后出现的资源无序竞争、提高系统运行效率。
其示例demo如下:
@Override public void afterPropertiesSet() throws Exception { threadPoolTaskScheduler.setPoolSize(1); threadPoolTaskScheduler.schedule(new Runnable() { @SneakyThrows @Override public void run() { Thread.sleep(10000); System.out.println("测试111111111111111111111111111111"); } }, new CronTrigger("0/10 * * * * *")); threadPoolTaskScheduler.schedule(new Runnable() { @SneakyThrows @Override public void run() { Thread.sleep(10000); System.out.println("测试22222222222222222222222222222222"); } }, new CronTrigger("0/10 * * * * *")); }
可以看到在PoolSize为1的情况下,测试1和2任务只会有一个运行,另外的任务处于阻塞状态。
有时候,关于ScheduledThreadPoolExecutor和ThreadPoolTaskScheduler有点难以分辨,但是它们二者其实也是互斥的,两者在IOC容器中只能选择一个,其原因为:
public class TaskSchedulingAutoConfiguration { public TaskSchedulingAutoConfiguration() { } @Bean @ConditionalOnBean( name = {"org.springframework.context.annotation.internalScheduledAnnotationProcessor"} ) @ConditionalOnMissingBean({SchedulingConfigurer.class, TaskScheduler.class, ScheduledExecutorService.class}) public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) { return builder.build(); }
通常我们会选择ThreadPoolTaskScheduler,因为其定时功能更强大一些。可以自定义trigger,而ScheduledThreadPoolExecutor的定时确没这么灵活。
更多推荐
所有评论(0)