Java Spring怎么实现定时任务

java实现定时任务

jdk自带的库中,有两种方式可以实现定时任务,一种是timer,另一种是scheduledthreadpoolexecutor。

Timer+TimerTask

创建一个Timer就创建了一个线程,可以用来调度TimerTask任务

Java Spring怎么实现定时任务

Timer有四个构造方法,可以指定Timer线程的名字以及是否设置为为守护线程。默认名字Timer-编号,默认不是守护线程。

主要有三个比较重要的方法:

立即学习“Java免费学习笔记(深入)”;

cancel():终止任务调度,取消当前调度的所有任务,正在运行的任务不受影响

purge():从任务队列中移除所有已经取消的任务

schedule:开始调度任务,提供了几个重载方法:

schedule(TimerTask task, long delay)延时执行,表示delay毫秒后执行一次task任务

schedule(TimerTask task, Date time)`指定时间执行,到`time`时间的时候执行一次`taskschedule(TimerTask task, long delay, long period)`延时周期执行,经过`delay`毫秒后每`period`毫秒执行一次`taskschedule(TimerTask task, Date firstTime, long period)`指定时间后周期执行,到达指定时间`firstTime`后每`period`毫秒执行一次`task

示例

public class TimerTest {    public static void main(String[] args) {        Timer timer = new Timer("aa");        Task task = new Task();        timer.schedule(task,new Date(),1000);    }}class Task extends TimerTask{    @Override    public void run() {        System.out.println(new Date());    }}

登录后复制

输出:
Thu Jul 07 14:50:02 CST 2022
Thu Jul 07 14:50:03 CST 2022
Thu Jul 07 14:50:04 CST 2022
Thu Jul 07 14:50:05 CST 2022
…………

弊端

Timer是单一线程的,且不会抛出异常。如果定时任务产生异常,整个线程将停止,从而导致定时任务终止。

ScheduledThreadPoolExecutor

因为Timer的缺陷,所以不建议使用Timer,建议使用ScheduledThreadPoolExecutor。

ScheduledThreadPoolExecutor是Timer的替代者,于JDK1.5引入,继承了ThreadPoolExecutor,是基于线程池设计的定时任务类。

主要的调度方法:

Java Spring怎么实现定时任务

schedule只执行一次调度,(任务,延迟时间,延迟时间单位)

scheduleAtFixedRate按固定的频率调度,如果执行时间过长,下次调度会延迟,(任务,第一次执行的延迟时间,周期,时间单位)

scheduleWithFixedDelay延迟调度,一次任务执行完后加上延迟时间执行下一次任务,(任务,第一次执行的延迟时间,间隔时间,时间单位)

示例

public class TimerTest {    public static void main(String[] args) throws Exception{        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);        scheduledExecutorService.scheduleAtFixedRate(                () -> System.out.println(new Date()),                1,3, TimeUnit.SECONDS);    }}

登录后复制

Spring定时任务

Spring定时任务主要靠@Scheduled注解实现,corn,fixedDelay,fixedDelayString,fixedRate,fixedRateString五个参数必须指定其一,传两个或三个都会抛出异常

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Repeatable(Schedules.class)public @interface Scheduled {String CRON_DISABLED = ScheduledTaskRegistrar.CRON_DISABLED;    // cron表达式String cron() default "";    // 时区String zone() default "";    // 从上一次调用结束到下一次调用之间的固定时间long fixedDelay() default -1;    // 和fixedDelay意思相同,只是使用字符传格式,支持占位符。例如:fixedDelayString = "${time.fixedDelay}"String fixedDelayString() default "";    // 两次调用之间固定的毫秒数(不需要等待上次任务完成)long fixedRate() default -1;    // 同上,支持占位符String fixedRateString() default "";    // 第一次执行任务前延迟的毫秒数long initialDelay() default -1;    // 同上,支持占位符String initialDelayString() default "";}

登录后复制

示例

@Component@EnableSchedulingpublic class ScheduledTask {    @Scheduled(fixedDelay = 1000)    public void task(){        System.out.println("aaa");    }}

登录后复制

原理

项目启动ScheduledAnnotationBeanPostProcessor的postProcessAfterInitialization()方法扫描带有@Scheduled注解的方法:

@Overridepublic 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> annotatedMethods = MethodIntrospector.selectMethods(targetClass,(MethodIntrospector.MetadataLookup>) method -> {Set scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Scheduled.class, Schedules.class);return (!scheduledMethods.isEmpty() ? scheduledMethods : 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, scheduledMethods) ->                        // 调用processScheduled方法将定时任务的方法存放到任务队列中scheduledMethods.forEach(scheduled -> processScheduled(scheduled, method, bean)));if (logger.isTraceEnabled()) {logger.trace(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName +"': " + annotatedMethods);}}}return bean;}

登录后复制

protected void processScheduled(Scheduled scheduled, Method method, Object bean) {try {            // 创建任务线程Runnable runnable = createRunnable(bean, method);            // 解析到定时任务方式的标记,解析到正确的参数后会设置为TRUE,如果在解析到了其他的参数就会抛出异常boolean processedSchedule = false;String errorMessage ="Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required";Set tasks = new LinkedHashSet(4);// Determine initial delay 解析第一次的延迟(解析initialDelay参数)long initialDelay = scheduled.initialDelay();String initialDelayString = scheduled.initialDelayString();if (StringUtils.hasText(initialDelayString)) {                // initialDelay不能小于0Assert.isTrue(initialDelay = 0) {Assert.isTrue(!processedSchedule, errorMessage);processedSchedule = true;tasks.add(this.registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay)));}String fixedDelayString = scheduled.fixedDelayString();if (StringUtils.hasText(fixedDelayString)) {if (this.embeddedValueResolver != null) {fixedDelayString = this.embeddedValueResolver.resolveStringValue(fixedDelayString);}if (StringUtils.hasLength(fixedDelayString)) {Assert.isTrue(!processedSchedule, errorMessage);processedSchedule = true;try {fixedDelay = parseDelayAsLong(fixedDelayString);}catch (RuntimeException ex) {throw new IllegalArgumentException("Invalid fixedDelayString value "" + fixedDelayString + "" - cannot parse into long");}tasks.add(this.registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay)));}}// Check fixed rate 解析fixedRate参数long fixedRate = scheduled.fixedRate();if (fixedRate >= 0) {Assert.isTrue(!processedSchedule, errorMessage);processedSchedule = true;tasks.add(this.registrar.scheduleFixedRateTask(new FixedRateTask(runnable, fixedRate, initialDelay)));}String fixedRateString = scheduled.fixedRateString();if (StringUtils.hasText(fixedRateString)) {if (this.embeddedValueResolver != null) {fixedRateString = this.embeddedValueResolver.resolveStringValue(fixedRateString);}if (StringUtils.hasLength(fixedRateString)) {Assert.isTrue(!processedSchedule, errorMessage);processedSchedule = true;try {fixedRate = parseDelayAsLong(fixedRateString);}catch (RuntimeException ex) {throw new IllegalArgumentException("Invalid fixedRateString value "" + fixedRateString + "" - cannot parse into long");}tasks.add(this.registrar.scheduleFixedRateTask(new FixedRateTask(runnable, fixedRate, initialDelay)));}}// Check whether we had any attribute set            // 如果五个参数一个也没解析到,抛出异常Assert.isTrue(processedSchedule, errorMessage);// Finally register the scheduled tasks            // 并发控制将任务队列存入注册任务列表synchronized (this.scheduledTasks) {Set 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());}}

登录后复制

将任务解析并添加到任务队列后,交由ScheduledTaskRegistrar类的scheduleTasks方法添加(注册)定时任务到环境中

protected void scheduleTasks() {   if (this.taskScheduler == null) {       //获取ScheduledExecutorService对象,实际上都是使用ScheduledThreadPoolExecutor执行定时任务调度      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));      }   }}private void addScheduledTask(@Nullable ScheduledTask task) {   if (task != null) {      this.scheduledTasks.add(task);   }}

登录后复制

以上就是Java Spring怎么实现定时任务的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2625890.html

(0)
上一篇 2025年3月7日 00:46:48
下一篇 2025年3月7日 00:46:58

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • Java 中的异构系统集成和数据集成技术

    随着大数据和云计算技术的发展,企业和组织面临着多种异构系统的集成和数据交换的挑战。在这个背景下,java 的异构系统集成和数据集成技术得到了广泛的应用和发展。本文将从异构系统集成和数据集成的概念、java 中异构系统集成和数据集成的原理和应…

    编程技术 2025年3月7日
    200
  • Java 中的移动支付和金融科技技术

    随着人们生活方式和消费习惯的变化,移动支付和金融科技在全球范围内正在迅速发展。作为一种新兴的支付方式,移动支付已经成为了人们生活中不可或缺的一部分。java 作为一种强大的编程语言,在移动支付和金融科技领域也有着重要的作用。 移动支付的核心…

    编程技术 2025年3月7日
    200
  • Java 中的区块链和数字货币技术

    区块链和数字货币技术是如今最热门的技术之一,文章将对java中的区块链和数字货币技术进行探讨。 区块链是一个由多个块组成的链式结构网络,每个块存储着许多交易信息。 在Java中,区块链可以通过使用Spring Boot和Web3J等框架来实…

    编程技术 2025年3月7日
    200
  • Java语言中的微信小程序开发介绍

    微信小程序是一种轻量级的应用程序,可以在微信平台上运行,不需要下载安装,方便快捷。java语言作为一种广泛应用于企业级应用开发的语言,也可以用于微信小程序的开发。 在Java语言中,可以使用Spring Boot框架和第三方工具包来开发微信…

    编程技术 2025年3月7日
    200
  • Java语言中的云计算应用介绍

    云计算是近年来广受关注和推崇的一种计算模式,它通过集成计算和存储资源,并通过互联网提供这些资源给用户,为企业和个人提供更加灵活、可扩展的it服务。java作为一种广泛应用于企业级开发的编程语言,也成为了云计算应用中常见的语言之一。在这篇文章…

    编程技术 2025年3月7日
    200
  • Java语言中的在线支付应用开发介绍

    随着网络技术的不断发展和普及,线上支付的需求也越来越高。作为一门广泛应用于企业级开发的编程语言,java提供了丰富的库和工具,方便开发者开发高效、安全、可维护的在线支付应用。本文将介绍java语言中的在线支付应用开发,包括相关技术、安全性和…

    编程技术 2025年3月7日
    200
  • Java语言中的Hibernate框架介绍

    hibernate是一个开放源码的orm框架,它将关系型数据库和java程序之间的数据映射相互绑定,这样可以使开发人员更方便地访问数据库中的数据。使用hibernate框架可以大量减少编写sql语句的工作,提高应用程序的开发效率和可重用性。…

    编程技术 2025年3月7日
    200
  • Java语言中的网络架构设计知识介绍

    随着互联网的迅速发展,java作为一种具有广泛应用的编程语言,成为了网络架构设计的重要组成部分。java语言拥有众多的网络应用框架和库,具有高效、安全、可靠等特性,越来越多的企业在其产品中采用java语言作为主要的技术方案。 网络架构设计,…

    编程技术 2025年3月7日
    200
  • Java语言中的在线教育应用开发介绍

    java是一种广泛应用于互联网中的编程语言,它在在线教育应用开发中具有重要的地位。在这篇文章中,我们将介绍java语言在在线教育应用开发中的作用,并提供一些实用的开发技巧。 Java在在线教育应用开发中的优点 Java语言在在线教育应用开发…

    编程技术 2025年3月7日
    200
  • Java语言中的供应链应用开发介绍

    随着全球化的发展和全球市场的不断扩大,企业之间的供应关系和物流链变得愈发复杂。在这样的环境下,供应链管理变得日益重要。java语言作为一种广泛应用于企业应用开发的编程语言,已经被广泛应用于供应链管理领域。本文将介绍java语言在供应链应用开…

    编程技术 2025年3月7日
    200

发表回复

登录后才能评论