前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot @EnableScheduling 启用多线程

springboot @EnableScheduling 启用多线程

作者头像
路过君
发布2020-10-30 10:20:33
1.7K0
发布2020-10-30 10:20:33
举报

现象

使用@EnableScheduling注解后,可以发现所有任务都排队执行,并且调度器线程名称都是“taskScheduler-1”

原因

默认配置使用单线程调度器

解决方案

配置线程池任务调度器

代码语言:javascript
复制
@Bean
public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(10);
    return taskScheduler;
}

源码分析

  • org.springframework.scheduling.annotation.EnableScheduling
代码语言:javascript
复制
// 导入配置
@Import(SchedulingConfiguration.class)
  • org.springframework.scheduling.annotation.SchedulingConfiguration
代码语言:javascript
复制
// 注册调度注解处理器
@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
	return new ScheduledAnnotationBeanPostProcessor();
}
  • org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor
代码语言:javascript
复制
// 为registrar注入调度器实例
private void finishRegistration() {
	if (this.scheduler != null) {
		this.registrar.setScheduler(this.scheduler);
	}

	if (this.beanFactory instanceof ListableBeanFactory) {
		Map<String, SchedulingConfigurer> beans =
				((ListableBeanFactory) this.beanFactory).getBeansOfType(SchedulingConfigurer.class);
		List<SchedulingConfigurer> configurers = new ArrayList<>(beans.values());
		AnnotationAwareOrderComparator.sort(configurers);
		for (SchedulingConfigurer configurer : configurers) {
			configurer.configureTasks(this.registrar);
		}
	}

	if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) {
		// 从beanFactory查找调度器实例注入
		Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type");
		try {
			// Search for TaskScheduler bean...
			this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, false));
		}
		catch (NoUniqueBeanDefinitionException ex) {
			logger.trace("Could not find unique TaskScheduler bean", ex);
			try {
				this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, true));
			}
			catch (NoSuchBeanDefinitionException ex2) {
				if (logger.isInfoEnabled()) {
					logger.info("More than one TaskScheduler bean exists within the context, and " +
							"none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +
							"(possibly as an alias); or implement the SchedulingConfigurer interface and call " +
							"ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +
							ex.getBeanNamesFound());
				}
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			logger.trace("Could not find default TaskScheduler bean", ex);
			// Search for ScheduledExecutorService bean next...
			try {
				this.registrar.setScheduler(resolveSchedulerBean(this.beanFactory, ScheduledExecutorService.class, false));
			}
			catch (NoUniqueBeanDefinitionException ex2) {
				logger.trace("Could not find unique ScheduledExecutorService bean", ex2);
				try {
					this.registrar.setScheduler(resolveSchedulerBean(this.beanFactory, ScheduledExecutorService.class, true));
				}
				catch (NoSuchBeanDefinitionException ex3) {
					if (logger.isInfoEnabled()) {
						logger.info("More than one ScheduledExecutorService bean exists within the context, and " +
								"none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +
								"(possibly as an alias); or implement the SchedulingConfigurer interface and call " +
								"ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +
								ex2.getBeanNamesFound());
					}
				}
			}
			catch (NoSuchBeanDefinitionException ex2) {
				logger.trace("Could not find default ScheduledExecutorService bean", ex2);
				// Giving up -> falling back to default scheduler within the registrar...
				logger.info("No TaskScheduler/ScheduledExecutorService bean found for scheduled processing");
			}
		}
	}

	this.registrar.afterPropertiesSet();
}
  • org.springframework.scheduling.config.ScheduledTaskRegistrar
代码语言:javascript
复制
// 配置调度任务
protected void scheduleTasks() {
	// 如果没有任务调度器,则创建单线程调度器
	if (this.taskScheduler == null) {
		this.localExecutor = Executors.newSingleThreadScheduledExecutor();
		this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
	}
	if (this.triggerTasks != null) {
		for (TriggerTask task : this.triggerTasks) {
			addScheduledTask(scheduleTriggerTask(task));
		}
	}
	if (this.cronTasks != null) {
		for (CronTask task : this.cronTasks) {
			addScheduledTask(scheduleCronTask(task));
		}
	}
	if (this.fixedRateTasks != null) {
		for (IntervalTask task : this.fixedRateTasks) {
			addScheduledTask(scheduleFixedRateTask(task));
		}
	}
	if (this.fixedDelayTasks != null) {
		for (IntervalTask task : this.fixedDelayTasks) {
			addScheduledTask(scheduleFixedDelayTask(task));
		}
	}
}
  • java.util.concurrent.Executors
代码语言:javascript
复制
// 创建线程池容量为1的调度器
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
 return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-10-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 现象
  • 原因
  • 解决方案
  • 源码分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档