Springboot中ThreadPoolTaskExecutor、ScheduledThreadPoolExecutor和ThreadPoolTaskScheduler的区别和用法

本文详细介绍了Java中用于任务调度的三种线程池实现:ThreadPoolTaskExecutor用于异步任务处理,ScheduledThreadPoolExecutor支持延时和循环任务,而ThreadPoolTaskScheduler则专注于定时任务。通过配置和示例代码,展示了它们的使用场景和区别,强调了合理利用线程池以优化系统资源的重要性。

刚开始看到这三个类,我看了很久也没看出它们的区别。先分别对其做个简短介绍。

先介绍一下三个类的共性,都是为了对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的定时确没这么灵活。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值