java implements scheduled tasks
In the library that comes with Jdk, there are two ways to implement scheduled tasks, one is Timer
, the other is ScheduledThreadPoolExecutor
.
Timer TimerTask
Creating a Timer
creates a thread, which can be used to schedule TimerTask
tasks
Timer
has four construction methods, which can specify the name of the Timer
thread and whether to set it as a daemon thread. The default name is Timer-number
, which is not a daemon thread by default.
There are three main methods:
cancel()
: Terminate task scheduling, cancel all currently scheduled tasks, and running tasks will not be affected
purge()
: Remove all canceled tasks from the task queue
schedule
: Start scheduling tasks, providing several overloaded methods :
schedule(TimerTask task, long delay)
Delayed execution, which means delay
will be executed once after task
task
schedule(TimerTask task, Date time)`Execute at the specified time, and execute `task once at `time` time
#schedule(TimerTask task, long delay, long period)`Delay cycle execution, after ` `task
schedule(TimerTask task, Date firstTime, long period)` is executed periodically after the specified time `firstTime` and is executed once every `period` milliseconds after the specified time `firstTime` is reached.
Example
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()); } }
Output:
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
…………
Disadvantages
Timer is single-threaded and does not throw exceptions. If an exception occurs in a scheduled task, the entire thread will stop, causing the scheduled task to terminate.
ScheduledThreadPoolExecutor
Due to the defects of Timer
, it is not recommended to use Timer
. It is recommended to use ScheduledThreadPoolExecutor
.
ScheduledThreadPoolExecutor
is a replacement for Timer
. It was introduced in JDK1.5 and inherits ThreadPoolExecutor
. It is a scheduled task class based on thread pool design. .
Main scheduling method:
schedule
Execute scheduling only once, (task, delay time, delay time unit)
scheduleAtFixedRate
Scheduling at a fixed frequency. If the execution time is too long, the next scheduling will be delayed, (task, delay time of the first execution, period, time unit)
scheduleWithFixedDelay
Delay scheduling, after a task is executed, a delay time is added to execute the next task, (task, delay time of the first execution, interval time, time unit)
Example
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 scheduled tasks
Spring scheduled tasks are mainly implemented by @Scheduled
annotations, corn, fixedDelay, fixedDelayString, fixedRate, fixedRateString
The five parameters are required Specifying one of them, passing two or three will throw an exception
@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 ""; }
Example
@Component @EnableScheduling public class ScheduledTask { @Scheduled(fixedDelay = 1000) public void task(){ System.out.println("aaa"); } }
Principle
Project startupScheduledAnnotationBeanPostProcessor
postProcessAfterInitialization ()
Method scans methods with @Scheduled
annotations:
@Override 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> 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 methods annotatedMethods.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<ScheduledTask> tasks = new LinkedHashSet<>(4); // Determine initial delay 解析第一次的延迟(解析initialDelay参数) long initialDelay = scheduled.initialDelay(); String initialDelayString = scheduled.initialDelayString(); if (StringUtils.hasText(initialDelayString)) { // initialDelay不能小于0 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 = parseDelayAsLong(initialDelayString); } 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)))); } } } // 第一次延迟参数小于0,默认为0 // At this point we don't need to differentiate between initial delay set or not anymore if (initialDelay < 0) { initialDelay = 0; } // Check fixed delay 解析fixedDelay参数 long fixedDelay = scheduled.fixedDelay(); if (fixedDelay >= 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<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()); } }
After the task is parsed and added to the task queue, it is handed over to the ScheduledTaskRegistrar
class ##scheduleTasksMethod to add (register) scheduled tasks to the environment
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); } }
The above is the detailed content of How to implement scheduled tasks in Java Spring. For more information, please follow other related articles on the PHP Chinese website!

java实现定时任务Jdk自带的库中,有两种方式可以实现定时任务,一种是Timer,另一种是ScheduledThreadPoolExecutor。Timer+TimerTask创建一个Timer就创建了一个线程,可以用来调度TimerTask任务Timer有四个构造方法,可以指定Timer线程的名字以及是否设置为为守护线程。默认名字Timer-编号,默认不是守护线程。主要有三个比较重要的方法:cancel():终止任务调度,取消当前调度的所有任务,正在运行的任务不受影响purge():从任务队

一、@RequestParam注解对应的axios传参方法以下面的这段Springjava代码为例,接口使用POST协议,需要接受的参数分别是tsCode、indexCols、table。针对这个Spring的HTTP接口,axios该如何传参?有几种方法?我们来一一介绍。@PostMapping("/line")publicList

SpringBoot和SpringCloud都是SpringFramework的扩展,它们可以帮助开发人员更快地构建和部署微服务应用程序,但它们各自有不同的用途和功能。SpringBoot是一个快速构建Java应用的框架,使得开发人员可以更快地创建和部署基于Spring的应用程序。它提供了一个简单、易于理解的方式来构建独立的、可执行的Spring应用

随着技术的更新迭代,Java5.0开始支持注解。而作为java中的领军框架spring,自从更新了2.5版本之后也开始慢慢舍弃xml配置,更多使用注解来控制spring框架。

1.Spring项目的创建1.1创建Maven项目第一步,创建Maven项目,Spring也是基于Maven的。1.2添加spring依赖第二步,在Maven项目中添加Spring的支持(spring-context,spring-beans)在pom.xml文件添加依赖项。org.springframeworkspring-context5.2.3.RELEASEorg.springframeworkspring-beans5.2.3.RELEASE刷新等待加载完成。1.3创建启动类第三步,创

作为一名Java开发者,学习和使用Spring框架已经是一项必不可少的技能。而随着云计算和微服务的盛行,学习和使用SpringCloud成为了另一个必须要掌握的技能。SpringCloud是一个基于SpringBoot的用于快速构建分布式系统的开发工具集。它为开发者提供了一系列的组件,包括服务注册与发现、配置中心、负载均衡和断路器等,使得开发者在构建微

SpringBean的生命周期管理一、SpringBean的生命周期通过以下方式来指定Bean的初始化和销毁方法,当Bean为单例时,Bean归Spring容器管理,Spring容器关闭,就会调用Bean的销毁方法当Bean为多例时,Bean不归Spring容器管理,Spring容器关闭,不会调用Bean的销毁方法二、通过@Bean的参数(initMethod,destroyMethod)指定Bean的初始化和销毁方法1、项目结构2、PersonpublicclassPerson{publicP

spring设计模式有:1、依赖注入和控制反转;2、工厂模式;3、模板模式;4、观察者模式;5、装饰者模式;6、单例模式;7、策略模式和适配器模式等。详细介绍:1、依赖注入和控制反转: 这两个设计模式是Spring框架的核心。通过依赖注入,Spring负责管理和注入组件之间的依赖关系,降低了组件之间的耦合度。控制反转则是指将对象的创建和依赖关系的管理交给Spring容器等等。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)