当前位置: 首页 > news >正文

做游戏特效的网站网站排名优化培训电话

做游戏特效的网站,网站排名优化培训电话,如何查公司网站谁家做的,怎么编辑网站在我们日常开发中经常会调度工具来处理一下需要定时执行的任务,比如定时导出报表数据给业务方发送邮件。你在工作中是如何这种定时调度? 如何实现调度任务 使用java技术栈的老铁来说,现成定时调度的解决方案应该有很多,总结来说…

在我们日常开发中经常会调度工具来处理一下需要定时执行的任务,比如定时导出报表数据给业务方发送邮件。你在工作中是如何这种定时调度?

如何实现调度任务

使用java技术栈的老铁来说,现成定时调度的解决方案应该有很多,总结来说有三大类:

1.开源的定时调度框架,如xxlJob。

2.使用java中的定时任务api自己写,比如Timer.

3.使用spring提供的@Scheduled注解,简单方便。

上述三种方案中,开源调度框架是最好用的,而且有可视化管理面板。但是这种开源框架通常需要单独部署和维护,成本较高,如果业务中调度任务不多的话,没有必要大费周折去部署和维护这么一套系统,得不偿失。

使用jdk自带的Timer,或者 ScheduledThreadPoolExecutor来自己手动实现,这种方式灵活度高,可更具业务进行自定义开发,但是jdk自带的api相对较为底层,不能很好的使用 cron表达式,如果想要使用的话,还需要实现一套cron表达式解析器的开发,开发成本较高。

使用spring提供的@Scheduled注解,通过简单配置一下cron表达式即可,再加上现在java应用开发,基本上都在使用spring全家桶,引用@Scheduled的成本不高。

Sping中调度任务是如何实现的

在使用spring的项目中 ,在一个方法上添加一个 @Scheduled 注解

然后根据业务需要添加需要的cron表达式(其实@Scheduled不仅仅支持cron表达式,还支持其他很多调度策略,详细可以看@Scheduled注解的定义)

最后在启动类上添加 @EnableScheduling 即可。

是不是很简单,完整代码如下:


@SpringBootApplication
@EnableScheduling
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}@Component
public class JobScheduler {@Scheduled(cron="0/1 * * * * ?")public void schedule(){System.out.println("scheduler" + new SimpleDateFormat("YYYY-MM-dd HH-mm:ss").format(new Date()) + "  :  "+Thread.currentThread().getName());}
}

这里可能就有老铁好奇了,为什么只添加了 @Scheduled 和 @EnableScheduling 两个注解,就可以实现调度的能力呢?

我们可以简单的看下 spring源码,探索一下它是如何实现的。

@EnableScheduling

当你在配置类上使用@EnableScheduling注解时,Spring会创建一个名为scheduledAnnotationProcessor的bean。这个过程是通过SchedulingConfiguration类实现的。SchedulingConfiguration类是@EnableScheduling注解导入的配置类,它负责创建ScheduledAnnotationBeanPostProcessor实例。

具体代码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {}@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {return new ScheduledAnnotationBeanPostProcessor();}}

在SchedulingConfiguration类中,定义了一个名为scheduledAnnotationProcessor的bean。这个bean是通过scheduledAnnotationProcessor()方法创建的,该方法返回一个新的ScheduledAnnotationBeanPostProcessor实例。

同时,@Role(BeanDefinition.ROLE_INFRASTRUCTURE)注解表示这个bean是基础设施bean,通常不会被应用程序代码直接使用。

ScheduledAnnotationBeanPostProcessor类主要负责解析@Scheduled注解并创建定时任务。

以下是解析@Scheduled注解并创建定时任务的详细过程(以cron任务做介绍,其他任务流程类似)。

1.处理bean

当Spring创建bean时,ScheduledAnnotationBeanPostProcessor的postProcessAfterInitialization方法会被调用。这个方法会检查bean中的所有方法,寻找带有@Scheduled注解的方法。

	public Object postProcessAfterInitialization(Object bean, String beanName) {if (bean instanceof AopInfrastructureBean || bean instanceof TaskScheduler ||bean instanceof ScheduledExecutorService) {// Ignore AOP infrastructure such as scoped proxies.return bean;}Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);if (!this.nonAnnotatedClasses.contains(targetClass) &&AnnotationUtils.isCandidateClass(targetClass, Arrays.asList(Scheduled.class, Schedules.class))) {Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass,(MethodIntrospector.MetadataLookup<Set<Scheduled>>) method -> {Set<Scheduled> scheduledAnnotations = AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Scheduled.class, Schedules.class);return (!scheduledAnnotations.isEmpty() ? scheduledAnnotations : null);});if (annotatedMethods.isEmpty()) {this.nonAnnotatedClasses.add(targetClass);if (logger.isTraceEnabled()) {logger.trace("No @Scheduled annotations found on bean class: " + targetClass);}}else {// Non-empty set of methodsannotatedMethods.forEach((method, scheduledAnnotations) ->scheduledAnnotations.forEach(scheduled -> processScheduled(scheduled, method, bean)));if (logger.isTraceEnabled()) {logger.trace(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName +"': " + annotatedMethods);}}}return bean;}

2.创建定时任务

对于每个解析到的@Scheduled注解,ScheduledAnnotationBeanPostProcessor会创建一个定时任务。

它首先获取一个TaskScheduler实例(默认为 ThreadPoolTaskScheduler ),然后使用该实例为带有@Scheduled注解的方法创建一个定时任务,任务的执行策略根据注解中的属性确定。

这一步是在processScheduled方法的另一个重载版本中完成的。

	protected void processScheduled(Scheduled scheduled, Method method, Object bean) {try {Runnable runnable = createRunnable(bean, method);boolean processedSchedule = false;String errorMessage ="Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required";Set<ScheduledTask> tasks = new LinkedHashSet<>(4);// Determine initial delaylong initialDelay = convertToMillis(scheduled.initialDelay(), scheduled.timeUnit());String initialDelayString = scheduled.initialDelayString();if (StringUtils.hasText(initialDelayString)) {Assert.isTrue(initialDelay < 0, "Specify 'initialDelay' or 'initialDelayString', not both");if (this.embeddedValueResolver != null) {initialDelayString = this.embeddedValueResolver.resolveStringValue(initialDelayString);}if (StringUtils.hasLength(initialDelayString)) {try {initialDelay = convertToMillis(initialDelayString, scheduled.timeUnit());}catch (RuntimeException ex) {throw new IllegalArgumentException("Invalid initialDelayString value \"" + initialDelayString + "\" - cannot parse into long");}}}// Check cron expression  // cron表达式处理String cron = scheduled.cron();if (StringUtils.hasText(cron)) {String zone = scheduled.zone();if (this.embeddedValueResolver != null) {cron = this.embeddedValueResolver.resolveStringValue(cron);zone = this.embeddedValueResolver.resolveStringValue(zone);}if (StringUtils.hasLength(cron)) {Assert.isTrue(initialDelay == -1, "'initialDelay' not supported for cron triggers");processedSchedule = true;if (!Scheduled.CRON_DISABLED.equals(cron)) {TimeZone timeZone;if (StringUtils.hasText(zone)) {timeZone = StringUtils.parseTimeZoneString(zone);}else {timeZone = TimeZone.getDefault();}tasks.add(this.registrar.scheduleCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone))));}}}// At this point we don't need to differentiate between initial delay set or not anymoreif (initialDelay < 0) {initialDelay = 0;}// Check fixed delay// 固定延迟......// Check fixed rate// 固定频次......// Check whether we had any attribute setAssert.isTrue(processedSchedule, errorMessage);// Finally register the scheduled taskssynchronized (this.scheduledTasks) {Set<ScheduledTask> regTasks = this.scheduledTasks.computeIfAbsent(bean, key -> new LinkedHashSet<>(4));regTasks.addAll(tasks);}}catch (IllegalArgumentException ex) {throw new IllegalStateException("Encountered invalid @Scheduled method '" + method.getName() + "': " + ex.getMessage());}}

3.创建Runnable
createRunnable方法用于创建一个Runnable实例,它封装了带有@Scheduled注解的方法的调用。这个Runnable实例将被传递给任务调度器。

	protected Runnable createRunnable(Object target, Method method) {Assert.isTrue(method.getParameterCount() == 0, "Only no-arg methods may be annotated with @Scheduled");Method invocableMethod = AopUtils.selectInvocableMethod(method, target.getClass());return new ScheduledMethodRunnable(target, invocableMethod);}

4.创建Trigger
createTrigger方法根据@Scheduled注解的属性创建一个Trigger实例。Trigger实例决定了任务的执行策略,如固定速率、固定延迟或Cron表达式。

	public CronTrigger(String expression, ZoneId zoneId) {Assert.hasLength(expression, "Expression must not be empty");Assert.notNull(zoneId, "ZoneId must not be null");this.expression = CronExpression.parse(expression);this.zoneId = zoneId;}

5.配置调度任务

根据cron表达式对业务逻辑进行调度

public ScheduledTask scheduleCronTask(CronTask task) {ScheduledTask scheduledTask = this.unresolvedTasks.remove(task);boolean newTask = false;if (scheduledTask == null) {scheduledTask = new ScheduledTask(task);newTask = true;}if (this.taskScheduler != null) {scheduledTask.future = this.taskScheduler.schedule(task.getRunnable(), task.getTrigger());}else {addCronTask(task);this.unresolvedTasks.put(task, scheduledTask);}return (newTask ? scheduledTask : null);}

从整个流程看下来,还是很复杂的,只不过这个复杂的流程,交给了spring自身来处理,只暴露给用户一个@Scheduled注解,简单的配置一下就可以。

到这里呢,spring的对@Scheduled 注解的解析和我们在日常开发中使用 @Scheduled的方式,想必你已经很清楚了,不过通过走读源码,大概也会发现一些问题:

1.cron表达式不能动态修改,如果想要调整调度策略的话,需要修改cron表达式,并重启项目才可以。

2.调度任务使用的 调度线程池是spring中默认的,线程池的大小,队里长度,拒绝策略都是什么?如何自定义个线程池提供给spring使用?

这两个问题,我们发到下一篇文中,进一步说明。


文章转载自:
http://dinncobestrid.ssfq.cn
http://dinncomatronlike.ssfq.cn
http://dinncojuso.ssfq.cn
http://dinncolevite.ssfq.cn
http://dinncotricklet.ssfq.cn
http://dinncomonosymptomatic.ssfq.cn
http://dinncosuperradiant.ssfq.cn
http://dinncobateau.ssfq.cn
http://dinncodeuterostome.ssfq.cn
http://dinncovilma.ssfq.cn
http://dinncoblida.ssfq.cn
http://dinncoartery.ssfq.cn
http://dinncokutaraja.ssfq.cn
http://dinncopataca.ssfq.cn
http://dinncomicrobic.ssfq.cn
http://dinncoarenulous.ssfq.cn
http://dinncospoilage.ssfq.cn
http://dinncoesv.ssfq.cn
http://dinncosilastic.ssfq.cn
http://dinnconeanderthalic.ssfq.cn
http://dinncopriss.ssfq.cn
http://dinnconotifiable.ssfq.cn
http://dinncotallow.ssfq.cn
http://dinncoflocky.ssfq.cn
http://dinncosemireligious.ssfq.cn
http://dinncoparacetaldehyde.ssfq.cn
http://dinncoexoergic.ssfq.cn
http://dinncoknurled.ssfq.cn
http://dinncoaccountancy.ssfq.cn
http://dinncosemifinal.ssfq.cn
http://dinncoseakeeping.ssfq.cn
http://dinncobiotypology.ssfq.cn
http://dinncosynergetic.ssfq.cn
http://dinncoboxhaul.ssfq.cn
http://dinncosolo.ssfq.cn
http://dinncounsensible.ssfq.cn
http://dinncoemblemize.ssfq.cn
http://dinncohypogenesis.ssfq.cn
http://dinncoarcograph.ssfq.cn
http://dinncourbanism.ssfq.cn
http://dinncoroberta.ssfq.cn
http://dinnconecessity.ssfq.cn
http://dinncorecording.ssfq.cn
http://dinnconegritic.ssfq.cn
http://dinncoridable.ssfq.cn
http://dinncoallergist.ssfq.cn
http://dinncocattery.ssfq.cn
http://dinncocollocation.ssfq.cn
http://dinncomeanspirited.ssfq.cn
http://dinncoversatilely.ssfq.cn
http://dinncoantihistamine.ssfq.cn
http://dinncostreptococcic.ssfq.cn
http://dinnconarrowcast.ssfq.cn
http://dinncounbelieving.ssfq.cn
http://dinncoatrophic.ssfq.cn
http://dinncogrissel.ssfq.cn
http://dinncosafeblowing.ssfq.cn
http://dinncooutrelief.ssfq.cn
http://dinncomartemper.ssfq.cn
http://dinncosiciliano.ssfq.cn
http://dinncobaton.ssfq.cn
http://dinncosupervise.ssfq.cn
http://dinncoalderney.ssfq.cn
http://dinncoclinique.ssfq.cn
http://dinncosowntown.ssfq.cn
http://dinncotrover.ssfq.cn
http://dinncoduodenitis.ssfq.cn
http://dinncoeric.ssfq.cn
http://dinncocambrel.ssfq.cn
http://dinncoimpoverishment.ssfq.cn
http://dinncotrysail.ssfq.cn
http://dinncoeloquence.ssfq.cn
http://dinncokingsoft.ssfq.cn
http://dinncofavus.ssfq.cn
http://dinncomower.ssfq.cn
http://dinncoameliorable.ssfq.cn
http://dinncodorsiflexion.ssfq.cn
http://dinncoburdensome.ssfq.cn
http://dinncosulphinpyrazone.ssfq.cn
http://dinncoquillet.ssfq.cn
http://dinncocloying.ssfq.cn
http://dinncojuncaceous.ssfq.cn
http://dinncobronchitis.ssfq.cn
http://dinncolexicostatistics.ssfq.cn
http://dinncochlorid.ssfq.cn
http://dinncoporbeagle.ssfq.cn
http://dinncopaderborn.ssfq.cn
http://dinncobouquetin.ssfq.cn
http://dinncokevazingo.ssfq.cn
http://dinncojacksy.ssfq.cn
http://dinncomanicou.ssfq.cn
http://dinncolaying.ssfq.cn
http://dinncosoteriology.ssfq.cn
http://dinncorance.ssfq.cn
http://dinncoovergrowth.ssfq.cn
http://dinncoconfederacy.ssfq.cn
http://dinncocampong.ssfq.cn
http://dinncodemosthenes.ssfq.cn
http://dinncosiceliot.ssfq.cn
http://dinncoobduct.ssfq.cn
http://www.dinnco.com/news/107783.html

相关文章:

  • 做正规小说网站有哪些搜全网的浏览器
  • 申请网站到哪里大的网站建设公司
  • 公司做网站之前要准备什么谷歌排名查询
  • 定制型网站建设多少钱关键洞察力
  • 广州外贸独立网站制作电商网络推广是什么
  • 互联网代理seo含义
  • 个人做论坛网站有哪些百度注册新账号
  • 网站建设工作进度计划表石家庄网站优化
  • 公司网站建设与管理的作用游戏推广代理app
  • 上海网站建设公司怎么分辨好坏seo标题生成器
  • 武夷山网站推广中国疫情最新情况
  • 深圳企业网站建设电话网站免费搭建平台
  • 绵阳住房和城乡建设厅网站武汉网站seo推广
  • 南阳网站建设.com品牌营销平台
  • 潍坊网站制作价格指数分布
  • 潍坊高新区建设局门户网站有没有专门做策划的公司
  • wordpress如何导入数据库沈阳seo
  • 网络营销服务是什么seo如何优化一个网站
  • 怎样做货源网站企业网站优化公司
  • 建站宝盒破解版向日葵seo
  • 提供网站建设公司报价百度推广和百度竞价有什么区别
  • 芜湖建设机械网站免费的建站平台
  • 网站建设周期计划湖南专业关键词优化服务水平
  • 网站建设ppt方案模板下载seo搜索引擎优化教程
  • 做交易网站需要用到的软件有哪些seo培训学院官网
  • 怎么做整人点不完的网站视频网站开发合同
  • 好用的软件下载网站企业网站定制开发
  • 怎么样做个网站潍坊网站建设优化
  • 南阳做网站优化公司百度域名收录
  • 各大网站图片昆明seo案例