spring定时任务详解

本文详细介绍了Spring定时任务的使用方法和源码解析,包括ScheduledAnnotationBeanPostProcessor如何处理@Scheduled注解的方法,以及ThreadPoolTaskScheduler的工作原理。在ScheduledAnnotationBeanPostProcessor中,任务被包装并放入调度器。ThreadPoolTaskScheduler创建的ScheduledThreadPoolExecutor使用DelayQueue进行任务调度,核心线程池大小由poolSize配置,支持周期性和非周期性任务的执行。
摘要由CSDN通过智能技术生成

使用

很方便的使用方法是用@Scheduled注解,在Spring配置文件中加入相应的配置。

其中ThreadPoolTaskSchedulerpoolSize属性代表用于执行定时任务的线程数。例如有两个定时任务触发的时间相同,如果只有一个线程,那么有一个任务需要等到另一个任务执行完了才能执行,如果线程数是2则可以并行执行。

<task:annotation-driven executor="asyncTaskExecutor" scheduler="scheduledTaskExecutor"/>

<bean id="scheduledTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
		<property name="poolSize" value="${scheduledTaskExecutor.poolSize}"/>
	</bean>

源码解读

ScheduledAnnotationBeanPostProcessor

这个类会解析@Schedule注解的方法,获取方法检查是否没有参数,然后包装成ScheduledMethodRunnable,根据时间的配置是cron还是fixedDelay还是fixedRate,放进这个processor的一个Tasks的map中,这是三个以Rannable为key,时间配置为value的map.

    private final Map<Runnable, String> cronTasks = new HashMap();
    private final Map<Runnable, Long> fixedDelayTasks = new HashMap();
    private final Map<Runnable, Long> fixedRateTasks = new HashMap();

这个类实现了ApplicationListener<ContextRefreshedEvent>,监听ContextRefreshedEvent事件,当有ApplicationContext refresh完成之后,如果上文提到的三个map至少有一个不为空,则新建一个ScheduledTaskRegistrar,把三个map set进去,scheduler也set进去(这个scheduler应该就是在task:annotation-driven配置的)。

如果没有配置scheduler则会取applicationContext中所有的type是TaskSchedulerScheduledExecutorService的bean(只能有一个,否则会报错)。

最后调用registrar.afterPropertiesSet()实际是把上文中三个map里的task作为参数调用taskScheduler.schedule(),结果放入private final Set<ScheduledFuture<?>> scheduledFutures = new LinkedHashSet();中。

ThreadPoolTaskScheduler

Spring的ThreadPoolTaskScheduler类的hierarchy结构如图
ThreadPoolTaskScheduler类的hierarchy结构
这个对象在初始化时会生成一个ScheduledThreadPoolExecutor作为schedulerExecutor,这个事cunrrent包中的类。 核心线程池大小就是我们配置的poolSize属性,最大线程池大小是Integer.MAX_VALUE,keepAliveTime为0,队列是DelayedWorkQueue,这个队列有一个属性private final DelayQueue<RunnableScheduledFuture> dq = new DelayQueue<RunnableScheduledFuture>();对这个队列的操作实际是是对这个DelayQueue的操作,这个队列大小是Integer.MAX_VALUE

schedule方法实际是调用的ScheduledThreadPoolExecutor对象的schedule方法。
非周期性任务:

 public ScheduledFuture schedule(Runnable task, Date startTime) {
   
        ScheduledExecutorService executor = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值