springboot 定时任务@Scheduled 和 异步@Async

使用@EnableScheduling开启功能

@Configuration
@EnableScheduling
public class ScheduleConfig {
}

编写任务

@Component
public class ScheduledTasks {
     //表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms;
     @Scheduled(fixedDelay = 500)
     public void fixedDelay(){
     }
     //表示按一定的频率执行任务,参数类型为long,单位ms;
     @Scheduled(fixedRate = 500)
     public void fixedRate(){
     }
     //cron表达式,指定任务在特定时间执行;
     @Scheduled(cron="0 50 * * * ?")
     public void cron(){
     }
     //第一次1秒后执行,当执行完后2秒再执行
     @Scheduled(initialDelay = 1000, fixedDelay = 2000)
     public void initialDelay() {
     }
     // 可以从配置文件中读取
     @Scheduled(fixedDelayString = "${jobs.fixedDelay}")
     public void fixedDelayString() {
     }
     /**
       * cron:cron表达式,指定任务在特定时间执行;
       * fixedDelay:表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms;
       * fixedDelayString:与fixedDelay含义一样,只是参数类型变为String;
       * fixedRate:表示按一定的频率执行任务,参数类型为long,单位ms;
       * fixedRateString: 与fixedRate的含义一样,只是将参数类型变为String;
       * initialDelay:表示延迟多久再第一次执行任务,参数类型为long,单位ms;
       * initialDelayString:与initialDelay的含义一样,只是将参数类型变为String;
 	  */	
 }

配置(可选)

@Configuration
public class ScheduleConfig implements SchedulingConfigurer, AsyncConfigurer{
    //并行任务
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar){
        TaskScheduler taskScheduler = taskScheduler();
        taskRegistrar.setTaskScheduler(taskScheduler);
    }
    //并行任务使用策略:多线程处理(配置线程数等)
    @Bean
    public ThreadPoolTaskScheduler taskScheduler(){
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(20);
        scheduler.setThreadNamePrefix("task-");  //设置线程名开头
        scheduler.setAwaitTerminationSeconds(60);
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        return scheduler;
    }
    //异步任务
    public Executor getAsyncExecutor(){
        Executor executor = taskScheduler();
        return executor;
    }
    //异步任务 异常处理
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler(){
    	return new SimpleAsyncUncaughtExceptionHandler();
    }
}

定时任务线程池中,不管配置多少个线程,每次到定时点,只有一个线程去执行任务。假如配置fixedDelay=500,表示上一次任务执行完后,延迟500毫秒执行下次任务。如果任务执行需要500毫秒,那么任务的执行周期是500+500=1000毫秒。就算线程池中有多个线程,也会等那个任务执行完再选取一个线程再次执行任务。

@Bean("aaa")
public TaskScheduler  scheduler() {
    ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
    scheduler.setThreadNamePrefix("a");
    scheduler.setPoolSize(4);
    scheduler.initialize();
    return scheduler;
}
@Scheduled(fixedDelay = 500)
public void scheduled(){
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    LOGGER.info(Thread.currentThread().getName());
}
2018-10-11 10:18:44.705     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:45.710     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:46.714     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:47.715     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:48.716     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:49.719     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:50.720     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:51.722     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:52.723     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:53.724     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:54.725     com.demo.test.async.ScheduleService      : a1
2018-10-11 10:18:55.726     com.demo.test.async.ScheduleService      : a3
2018-10-11 10:18:56.727     com.demo.test.async.ScheduleService      : a3
2018-10-11 10:18:57.729     com.demo.test.async.ScheduleService      : a3

加入配置fixedRate = 500,表示每500毫秒执行一次任务。如果任务执行时间大于配置的值,则任务执行完毕立即执行下一个任务。

@Bean("aaa")
public TaskScheduler  scheduler() {
    ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
    scheduler.setThreadNamePrefix("a");
    scheduler.setPoolSize(4);
    scheduler.initialize();
    return scheduler;
}
@Scheduled(fixedRate = 500)
public void scheduled(){
    LOGGER.info(Thread.currentThread().getName());
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
2018-10-11 11:01:21.218  com.demo.test.async.ScheduleService      :   a1
2018-10-11 11:01:23.219  com.demo.test.async.ScheduleService      :   a2
2018-10-11 11:01:25.220  com.demo.test.async.ScheduleService      :   a1
2018-10-11 11:01:27.221  com.demo.test.async.ScheduleService      :   a1
2018-10-11 11:01:29.221  com.demo.test.async.ScheduleService      :   a1
2018-10-11 11:01:31.222  com.demo.test.async.ScheduleService      :   a4
2018-10-11 11:01:33.223  com.demo.test.async.ScheduleService      :   a4

可以看到任务执行时间是2秒,大于配置500毫秒,所以任务执行完立即执行下一个任务。相当于执行周期变成了任务执行时间。

如果同时开启了@EnableAsync和使用了@Async,便变成了按配置时间(T),每T执行一次任务。如果任务执行时间大于T,则会选取线程池中其他的线程去执行任务,如果没有剩余线程,则会等待有线程空闲出来。

@EnableAsync
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setTaskScheduler( scheduler());
    }
    @Bean("aaa")
    public TaskScheduler   scheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("a");
        scheduler.setPoolSize(4);
        scheduler.initialize();
        return scheduler;
    }
}
 @Async("aaa")
@Scheduled(fixedRate = 500)
public void scheduled(){
    LOGGER.info(Thread.currentThread().getName());
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
2018-10-11 11:12:35.326  com.demo.test.async.ScheduleService      :  a4
2018-10-11 11:12:35.830  com.demo.test.async.ScheduleService      :  a2
2018-10-11 11:12:36.338  com.demo.test.async.ScheduleService      :  a1
2018-10-11 11:12:36.830  com.demo.test.async.ScheduleService      :  a3
2018-10-11 11:12:37.326  com.demo.test.async.ScheduleService      :  a4
2018-10-11 11:12:37.836  com.demo.test.async.ScheduleService      :  a2
2018-10-11 11:12:38.338  com.demo.test.async.ScheduleService      :  a1
2018-10-11 11:12:38.830  com.demo.test.async.ScheduleService      :  a3

使用@EnableScheduling,同时不使用@EnableAsync和taskRegistrar也没有添加线程池,这时候执行定时任务,会使用默认的线程池(只有一个线程),多个任务同步执行
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
    }
}
@Scheduled(fixedRate = 500)
public void scheduled(){
    LOGGER.info(Thread.currentThread().getName() + " -- aaa");
}
@Scheduled(fixedDelay = 1000)
public void fileProcessScheduled(){
    LOGGER.info(Thread.currentThread().getName() + " -- bbb");
}
2018-10-12 09:28:32.415  com.demo.test.async.ScheduleService      : pool-1-thread-1 -- aaa
2018-10-12 09:28:32.429  com.demo.test.async.ScheduleService      : pool-1-thread-1 -- bbb
2018-10-12 09:28:32.915  com.demo.test.async.ScheduleService      : pool-1-thread-1 -- aaa
2018-10-12 09:28:33.415  com.demo.test.async.ScheduleService      : pool-1-thread-1 -- aaa
2018-10-12 09:28:33.431  com.demo.test.async.ScheduleService      : pool-1-thread-1 -- bbb
2018-10-12 09:28:33.915  com.demo.test.async.ScheduleService      : pool-1-thread-1 -- aaa

使用@EnableScheduling,同时不使用@EnableAsync,然后在taskRegistrar添加指定线程池,这时候执行定时任务,会使用我们添加的线程池,多个任务同步执行
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
     	taskRegistrar.setTaskScheduler(scheduler());
    }
    @Bean
    public TaskScheduler scheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("a");
        scheduler.setPoolSize(3);
        scheduler.initialize();
        return scheduler;
    }
}
@Scheduled(fixedRate = 500)
public void scheduled(){
    LOGGER.info(Thread.currentThread().getName() + " -- aaa");
}
@Scheduled(fixedDelay = 1000)
public void fileProcessScheduled(){
    LOGGER.info(Thread.currentThread().getName() + " -- bbb");
}
2018-10-12 09:38:09.763   com.demo.test.async.ScheduleService      : a2 -- aaa
2018-10-12 09:38:10.265   com.demo.test.async.ScheduleService      : a2 -- aaa
2018-10-12 09:38:10.276   com.demo.test.async.ScheduleService      : a1 -- bbb
2018-10-12 09:38:10.764   com.demo.test.async.ScheduleService      : a3 -- aaa
2018-10-12 09:38:11.264   com.demo.test.async.ScheduleService      : a3 -- aaa
2018-10-12 09:38:11.276   com.demo.test.async.ScheduleService      : a2 -- bbb
2018-10-12 09:38:11.764   com.demo.test.async.ScheduleService      : a1 -- aaa

使用@EnableScheduling@EnableAsync,然后在任务上用@Async("xxx")指定线程池,taskRegistrar添加不添加线程池无影响,会使用指定的,不会用registrar里添加的,这时候执行定时任务,会使用各自指定的线程池,多个任务(非一个线程池)并行执行
@EnableAsync
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
    }
    @Bean("aaa")
    public TaskScheduler   a() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("a");
        scheduler.setPoolSize(3);
        scheduler.initialize();
        return scheduler;
    }
    @Bean("bbb")
    public TaskScheduler fileProcessScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("b");
        scheduler.setPoolSize(2);
        scheduler.initialize();
        return scheduler;
    }
}
@Async("aaa")
@Scheduled(fixedRate = 500)
public void scheduled(){
     try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    LOGGER.info(Thread.currentThread().getName() + " -- aaa");
}
@Async("bbb")
@Scheduled(fixedDelay = 1000)
public void fileProcessScheduled(){
    LOGGER.info(Thread.currentThread().getName() + " -- bbb");
}
2018-10-12 09:43:54.484   com.demo.test.async.ScheduleService      : a2 -- aaa
2018-10-12 09:43:54.498   com.demo.test.async.ScheduleService      : b2 -- bbb
2018-10-12 09:43:54.985   com.demo.test.async.ScheduleService      : a3 -- aaa
2018-10-12 09:43:55.484   com.demo.test.async.ScheduleService      : a1 -- aaa
2018-10-12 09:43:55.498   com.demo.test.async.ScheduleService      : b1 -- bbb
2018-10-12 09:43:55.984   com.demo.test.async.ScheduleService      : a2 -- aaa
2018-10-12 09:43:56.485   com.demo.test.async.ScheduleService      : a3 -- aaa
2018-10-12 09:43:56.498   com.demo.test.async.ScheduleService      : b2 -- bbb
2018-10-12 09:43:56.984   com.demo.test.async.ScheduleService      : a1 -- aaa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值