Spring Boot-定时任务

目录

1.创建任务类

2.开启定时任务

3.执行时间的配置

4.多线程处理定时任务


1.创建任务类

@Component
public class SchedulerTask1 {

    private Log log= LogFactory.getLog(SchedulerTask1.class);

    @Scheduled(cron = "0/5 * * * * *")
    public void scheduled(){
        //打印出当前时间和执行定时任务的线程名称
        System.out.println("=====>>>>>使用cron  {}======"+new Date().toString()+"======"+Thread.currentThread().getName());
    }

    @Scheduled(fixedRate=5000)
    public void scheduled1() {
        //打印出当前时间和执行定时任务的线程名称
        System.out.println("=====>>>>>使用fixedRate{}==="+new Date().toString()+"======"+Thread.currentThread().getName());
    }

    @Scheduled(fixedDelayString = "${jobs.fixedDelay}")
    public void scheduled2() {
        //打印出当前时间和执行定时任务的线程名称
        System.out.println("=====>>>>>fixedDelay{}======"+new Date().toString()+"======"+Thread.currentThread().getName());
    }
}

 

2.开启定时任务

在Spring Boot中使用定时任务需要将@EnableScheduling注解添加到启动类上,否则不会启动定时任务:

@SpringBootApplication
@EnableScheduling
public class SchedulerdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SchedulerdemoApplication.class, args);
    }

}

启动工程,查看定时任务打印出来的日志:

=====>>>>>使用cron  {}======Fri Mar 15 17:08:15 CST 2019======scheduling-1
=====>>>>>使用fixedRate{}===Fri Mar 15 17:08:18 CST 2019======scheduling-1
=====>>>>>fixedDelay{}======Fri Mar 15 17:08:18 CST 2019======scheduling-1
=====>>>>>使用cron  {}======Fri Mar 15 17:08:20 CST 2019======scheduling-1
=====>>>>>使用fixedRate{}===Fri Mar 15 17:08:23 CST 2019======scheduling-1
=====>>>>>fixedDelay{}======Fri Mar 15 17:08:23 CST 2019======scheduling-1
=====>>>>>使用cron  {}======Fri Mar 15 17:08:25 CST 2019======scheduling-1
=====>>>>>使用fixedRate{}===Fri Mar 15 17:08:28 CST 2019======scheduling-1
=====>>>>>fixedDelay{}======Fri Mar 15 17:08:28 CST 2019======scheduling-1

我们可以在控制台的打印出来的日志信息中可以看到,我们定义的三个任务都已经出发并执行了,定时任务都是在同一个线程池用同一个线程来处理的。

 

3.执行时间的配置

在上面的定时任务中,我们在方法上使用@Scheduled注解来设置任务的执行时间,通过看 @Scheduled源码可以看出它支持多种参数:

  1. cron:cron表达式,指定任务在特定时间执行;
  2. fixedDelay:表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms;
  3. fixedDelayString:与fixedDelay含义一样,只是参数类型变为String;
  4. fixedRate:表示按一定的频率执行任务,参数类型为long,单位ms;
  5. fixedRateString: 与fixedRate的含义一样,只是将参数类型变为String;
  6. initialDelay:表示延迟多久再第一次执行任务,参数类型为long,单位ms;
  7. initialDelayString:与initialDelay的含义一样,只是将参数类型变为String;
  8. zone:时区,默认为当前时区,一般没有用到;

 

4.多线程处理定时任务

看到控制台输出的结果,所有的定时任务都是通过一个线程来处理的,我估计是在定时任务的配置中设定了一个SingleThreadScheduledExecutor,于是我看了源码,从ScheduledAnnotationBeanPostProcessor类开始一路找下去。果然,在ScheduledTaskRegistrar(定时任务注册类)中的scheduleTasks()方法中有这样一段判断:

	protected void scheduleTasks() {
		if (this.taskScheduler == null) {
			this.localExecutor = Executors.newSingleThreadScheduledExecutor();
			this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
		}
        ....
	}

这就说明如果taskScheduler为空,那么就给定时任务做了一个单线程的线程池,正好在这个类中还有一个设置taskScheduler的方法:

	public void setScheduler(@Nullable Object scheduler) {
		if (scheduler == null) {
			this.taskScheduler = null;
		}
		else if (scheduler instanceof TaskScheduler) {
			this.taskScheduler = (TaskScheduler) scheduler;
		}
		else if (scheduler instanceof ScheduledExecutorService) {
			this.taskScheduler = new ConcurrentTaskScheduler(((ScheduledExecutorService) scheduler));
		}
		else {
			throw new IllegalArgumentException("Unsupported scheduler type: " + scheduler.getClass());
		}
	}

 

这样问题就很简单了,我们只需用调用这个方法显式的设置一个ScheduledExecutorService就可以达到并发的效果了。我们要做的仅仅是实现SchedulingConfigurer接口,重写configureTasks方法就OK了:

@Configuration
public class ScheduleConfig implements SchedulingConfigurer{
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        //设定一个长度10的定时任务线程池
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
    }
}

多线程并发执行定时任务结果:

=====>>>>>fixedDelay{}======Fri Mar 15 17:41:18 CST 2019======pool-1-thread-7
=====>>>>>使用cron  {}======Fri Mar 15 17:41:20 CST 2019======pool-1-thread-8
=====>>>>>使用fixedRate{}===Fri Mar 15 17:41:23 CST 2019======pool-1-thread-4
=====>>>>>fixedDelay{}======Fri Mar 15 17:41:23 CST 2019======pool-1-thread-9
=====>>>>>使用cron  {}======Fri Mar 15 17:41:25 CST 2019======pool-1-thread-3
=====>>>>>使用fixedRate{}===Fri Mar 15 17:41:28 CST 2019======pool-1-thread-10
=====>>>>>fixedDelay{}======Fri Mar 15 17:41:28 CST 2019======pool-1-thread-5
=====>>>>>使用cron  {}======Fri Mar 15 17:41:30 CST 2019======pool-1-thread-6

还要一种配置多线程处理定时任务的方法

 首先编写配置类AsyncConfig:

@SpringBootConfiguration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {


    @Override
    public Executor getAsyncExecutor() {

        // ThredPoolTaskExcutor的处理流程
        // 当池子大小小于corePoolSize,就新建线程,并处理请求
        // 当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去workQueue中取任务并处理
        // 当workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
        // 当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁

        ThreadPoolTaskExecutor threadPoolTaskExecutor=new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(5);//核心池大小
        threadPoolTaskExecutor.setMaxPoolSize(10);//最大池大小
        threadPoolTaskExecutor.setQueueCapacity(25);
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

        // TODO Auto-generated method stub
        return null;
    }

}

 在配置类上通过@SpringBootConfiguration表明是一个配置类,通过@EnableAsync开启多线程的开关。然后在定时任务的方法上添加@Async注解,当程序调用这个方法就会开启一个线程去执行具体定义的任务:

    @Scheduled(fixedRate=5000)
    @Async
    public void scheduled1() {
        //打印出当前时间和执行定时任务的线程名称
        System.out.println("=====>>>>>使用fixedRate{}==="+new Date().toString()+"======"+Thread.currentThread().getName());
    }

程序运行结果:

=====>>>>>使用fixedRate{}===Fri Mar 15 17:50:47 CST 2019======ThreadPoolTaskExecutor-4
=====>>>>>fixedDelay{}======Fri Mar 15 17:50:47 CST 2019======ThreadPoolTaskExecutor-5
=====>>>>>使用cron  {}======Fri Mar 15 17:50:50 CST 2019======ThreadPoolTaskExecutor-2
=====>>>>>使用fixedRate{}===Fri Mar 15 17:50:52 CST 2019======ThreadPoolTaskExecutor-1
=====>>>>>fixedDelay{}======Fri Mar 15 17:50:52 CST 2019======ThreadPoolTaskExecutor-3
=====>>>>>使用cron  {}======Fri Mar 15 17:50:55 CST 2019======ThreadPoolTaskExecutor-4

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值