与Spring的计划任务一起按时运行

您是否需要每天像闹钟一样在同一时间运行某个流程? 然后,Spring的预定任务适合您。 允许您使用@Scheduled注释方法,以使其在指定的时间或内部间隔运行。 在本文中,我们将研究如何设置一个可以使用计划任务的项目,以及如何使用不同的方法来定义它们的执行时间。

我将在本文中使用Spring Boot,以使依赖关系变得简洁而又简单,这是因为可以对spring-boot-starter依赖项进行调度,该依赖项将以某种方式包含在几乎每个Spring Boot项目中。 这使您可以使用任何其他启动程序依赖项,因为它们会引入spring-boot-starter及其所有关系。 如果要包括确切的依赖项本身,请使用spring-context

您可以使用spring-boot-starter

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.0.0.RC1</version>
</dependency>

或直接使用spring-context

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.3.RELEASE</version>
</dependency>

创建计划任务非常简单。 将@Scheduled批注添加到希望自动运行的任何方法中,并将@EnableScheduling包含在配置文件中。

因此,例如,您可能会遇到类似以下的内容。

@Component
public class EventCreator {private static final Logger LOG = LoggerFactory.getLogger(EventCreator.class);private final EventRepository eventRepository;public EventCreator(final EventRepository eventRepository) {this.eventRepository = eventRepository;}@Scheduled(fixedRate = 1000)public void create() {final LocalDateTime start = LocalDateTime.now();eventRepository.save(new Event(new EventKey("An event type", start, UUID.randomUUID()), Math.random() * 1000));LOG.debug("Event created!");}
}

这里有很多代码对于运行计划任务并不重要。 正如我在一分钟前说过的,我们需要在方法上使用@Scheduled ,它将自动开始运行。 因此,在上面的示例中, create方法将每隔1000毫秒(1秒)开始运行,如注释的fixedRate属性所示。 如果我们想更改其运行频率,则可以增加或减少fixedRate时间,或者可以考虑使用可用的不同调度方法。

因此,您可能想知道这些其他方法是正确的吗? 好了,它们就在这里(我还将在此处包括fixedRate )。

  • fixedRatefixedRate调用之间以固定的毫秒周期执行该方法。
  • fixedRateString一样的fixedRate ,但有一个字符串值来代替。
  • fixedDelay在一次调用结束与下一次调用之间以固定的毫秒周期执行该方法。
  • fixedDelayString一样fixedDelay但一个字符串值来代替。
  • cron使用类似cron的表达式来确定何时执行该方法(我们将在以后更深入地介绍此方法)。

@Scheduled批注还有一些其他实用程序属性。

  • zone指示将解析cron表达式的时区,如果不包括时区,它将使用服务器的默认时区。 因此,如果您需要它在特定时区运行,例如香港,则可以使用zone = "GMT+8:00"
  • initialDelay延迟第一次执行计划任务的毫秒数,需要使用固定速率或固定延迟属性之一。
  • initialDelayString同为initialDelay但一个字符串值来代替。

以下是一些使用固定速率和延迟的示例。

@Scheduled(fixedRate = 1000)

与之前相同,每1秒运行一次。

@Scheduled(fixedRateString = "1000")

同上。

@Scheduled(fixedDelay = 1000)

在上一次调用完成后运行1秒。

@Scheduled(fixedRate = 1000, initialDelay = 5000)

每秒运行一次,但要等待5秒钟才能首次执行。

现在来看一下cron属性,它可以对任务的计划进行更多控制,让我们定义任务运行的秒数,分钟数和小时数,甚至可以进一步指定任务的运行年限。

以下是构建cron表达式的组件的细分。

  • Seconds值可以为0-59或特殊字符, - * /
  • Minutes值可以为0-59或特殊字符, - * /
  • Hours值可以为0-59或特殊字符, - * /
  • Day of month可以具有值1-31或特殊字符, - * ? / LWC , - * ? / LWC
  • Month值可以为1-12JAN-DEC或特殊字符, - * /
  • Day of week可以具有值1-7SUN-SAT或特殊字符, - * ? / LC # , - * ? / LC #
  • Year可以为空,值为1970-2099或特殊字符, - * /

为了更加清楚起见,我将细目分类组合成一个由字段标签组成的表达式。

@Scheduled(cron = "[Seconds] [Minutes] [Hours] [Day of month] [Month] [Day of week] [Year]")

请不要在表达式中包括花括号(我使用它们使表达式更清晰)。

在继续之前,我们需要了解特殊字符的含义。

  • *表示所有值,因此,如果在第二个字段中使用,则表示每秒或在天字段中使用,表示每天运行。
  • ? 表示没有特定的值,并且可以在“月的天”或“星期几”字段中使用,其中使用一个会使另一个无效。 如果我们指定在一个月的15日触发,则一个? 将在“ Day of week字段中使用。
  • -表示值的范围(例如,小时数字段中的1-3表示小时数1、2和3)。
  • ,代表附加价值,例如周一,周三,SUN在本周,说明此一天,在周一,周三和周日。
  • /代表增量,例如,秒字段中的0/15从0(0、15、30和45)开始每15秒触发一次。
  • L代表一周或一个月的最后一天。 请记住,在这种情况下,星期六是一周的结束,因此在“星期几”字段中使用L将在星期六触发。 可以将其与月日字段中的数字结合使用,例如6L代表月的最后一个星期五,或者L-3这样的表达式表示月的最后一天。 如果我们在星期几字段中指定一个值,则必须使用? 在“月”字段中,反之亦然。
  • W表示每月的最接近的工作日。 例如,如果15W是工作日,则在每月的第15天触发,否则它将在最近的工作日运行。 该值不能在日期值列表中使用。
  • #指定任务应该在星期几和星期几触发。 例如, 5#2表示该月的第二个星期四。 如果您指定的日期和星期溢出到下个月,则不会触发。

在这里可以找到有用的资源,其中的解释稍长一些,这有助于我撰写本文。

让我们来看几个例子。

@Scheduled(cron = "0 0 12 * * ?")

每天晚上12点开火。

@Scheduled(cron = "0 15 10 * * ? 2005")

2005年每天早上10:15触发。

@Scheduled(cron = "0/20 * * * * ?")

每20秒触发一次。

有关更多示例,请参阅我前面提到的链接, 此处再次显示。 幸运的是,如果您在编写一个简单的cron表达式时遇到麻烦,那么您应该可以在Google中找到所需的方案,因为有人可能已经在Stack Overflow上问了同样的问题。

要将上述内容与一个小的代码示例绑定在一起,请参见下面的代码。

@Component
public class AverageMonitor {private static final Logger LOG = LoggerFactory.getLogger(AverageMonitor.class);private final EventRepository eventRepository;private final AverageRepository averageRepository;public AverageMonitor(final EventRepository eventRepository, final AverageRepository averageRepository) {this.eventRepository = eventRepository;this.averageRepository = averageRepository;}@Scheduled(cron = "0/20 * * * * ?")public void publish() {final double average =eventRepository.getAverageValueGreaterThanStartTime("An event type", LocalDateTime.now().minusSeconds(20));averageRepository.save(new Average(new AverageKey("An event type", LocalDateTime.now()), average));LOG.info("Average value is {}", average);}
}

在这里,我们有一个类,每20秒向Cassandra查询一次同一时间段内事件的平均值。 同样,这里的大多数代码都是@Scheduled批注中的噪音,但在野外看到它可能会有所帮助。 此外,如果您观察到这一情况,则对于每20秒运行一次的用例,在此处使用频繁运行任务的情况下,使用fixedRate以及可能使用fixedDelay属性而不是cron更为合适。

@Scheduled(fixedRate = 20000)

是上面使用的cron表达式的fixedRate等效项。

我前面提到的最终要求是将@EnableScheduling批注添加到配置类。

@SpringBootApplication
@EnableScheduling
public class Application {public static void main(final String args[]) {SpringApplication.run(Application.class);}
}

作为一个很小的Spring Boot应用程序,我已将@EnableScheduling批注附加到主@SpringBootApplication类。

总而言之,我们可以安排任务使用@Scheduled注释以及执行之间的毫秒级速率或cron表达式来触发,以实现无法用前者表达的更佳时序。 对于需要非常频繁运行的任务,使用fixedRatefixedDelay属性就足够了,但是一旦执行之间的时间变大,则很难快速确定所定义的时间。 发生这种情况时,应使用cron属性以更好地了解计划的时间。

这篇文章中使用的少量代码可以在我的GitHub上找到 。

如果您发现这篇文章很有帮助,并希望在我撰写新教程时保持最新,请在Twitter上@LankyDanDev关注我。

翻译自: https://www.javacodegeeks.com/2018/02/running-time-springs-scheduled-tasks.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348246.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jboss url路径_在JBoss的服务器端正确解码URL参数

jboss url路径我今天花了很多时间来弄清楚如何在运行在JBoss上的JSF应用程序中&#xff08;使用JBoss 7 Final&#xff09;强制正确解码编码的字符。 当您有例如通过URL传递中文字符时&#xff0c;就会发生此问题。 假设您有指点事件&#xff0c;编码为&#xff05;E6&#xff…

在JDK 10中不可变与不可修改

大约两个月前&#xff0c; 斯图尔特马克斯 &#xff08; Stuart Marks&#xff09;写道&#xff1a;“ 不变性就像葡萄酒 。” 然后&#xff0c;他提醒读者注意叔本华的熵定律 &#xff1a;“如果将一勺酒倒入装满污水的桶中&#xff0c;就会产生污水。 如果将一勺污水倒入装满…

@async方法不调用了_在Spring中使用Future对象调用Async方法调用

async方法不调用了下一个示例将演示Spring容器内部的异步方法调用。 为什么我们需要异步方法调用&#xff1f; 在某些情况下&#xff0c;我们并不真正知道是否需要重播或何时应返回结果。 传统方式在Java EE世界中处理异步调用的方法是使用队列/主题。 我们可以在Spring中进行相…

不同的休眠命名策略

本文讨论了hibernate提供的不同命名策略&#xff0c;以及命名策略从hibernate 4中的hibernate.ejb.naming_strategy到hibernate 5中的hibernate.implicit_naming_strategy和hibernate.physical_naming_strategy的转变。最后&#xff0c;我们将研究一下在休眠和配置中实施自定义…

基于FPGA,如何用Verilog HDL实现64位宽的扰码器?附上仿真结果。

文章目录前言一、扰码器1、什么是扰码器2、扰码的原理3、产生扰码的多项式二、Scrambler的Verilog实现1、scrambler.v2、scrambler_tb.v三、仿真结果四、总结前言 在数字信号处理系统中&#xff0c;因为发送端的数字信号序列可能会出现很长一段都是“0”&#xff0c;或很长一段…

基于FPGA,解扰码器Verilog的实现,以及扰码器与解扰码器的联合仿真。附上仿真结果。

文章目录前言一、扰码器二、解扰码器三、Descrambler的Verilog实现1、descrambler.v2、descrambler_tb.v四、扰码器与解扰码器的联合仿真1、scrambler_test.v2、scrambler_test_tb.v3、联合仿真结果五、总结前言 在数字信号处理系统中&#xff0c;因为发送端的数字信号序列可能…

光纤通信系统简介

文章目录前言一、直接检测光通信系统二、相干光通信系统三、直接检测与相干检测1、直接检测2、相干检测3、相干检测的优缺点&#xff08;1&#xff09;相干检测的缺点&#xff08;2&#xff09;相干检测的优点总结参考文献前言 光通信系统的基本组成结构如下图所示。光通信系统…

epyc rome_使用Encog,ROME,JSoup和Google Guava进行博客分类

epyc rome继续进行编程收集情报 &#xff08; Programming Collection Intelligence &#xff0c;PCI&#xff09;&#xff0c;下一个练习是使用距离得分根据相关博客中使用的单词来确定博客列表。 我已经找到Encog作为AI /机器学习算法的框架&#xff0c;为此&#xff0c;我需…

重构字符串型系统

去年&#xff0c;我加入了一个项目&#xff0c;该项目接管了另一个未能满足客户需求的软件公司。 如您所知&#xff0c;在“继承”的项目及其代码库中&#xff0c;有许多事情可以并且应该加以改进。 可悲的是&#xff08;但并不奇怪&#xff09;领域模型就是这样一个孤零零&…

OFDM仿真程序,可直接运行,注释详细(没人注释比我还详细了)

OFDM仿真程序 clc clear allIFFT_bin_length128; %IFFT点数128个 carrier_count50; %子信道&#xff08;子载波&#xff09;数目 bits_per_symbol2; %4进制符号 symbols_per_carrier200;%每个子信道或者说子载波有200个符号 SNR0:1:40; for num1:41baseband_out_lengthcarrie…

Delta-Sigma调制(DSM)技术

前言 数字信号处理和通信系统的性能很大程度上受到了模拟信号到数字信号转换接口——ADC的精度和分辨率的限制。而传统的线性脉冲编码调制&#xff08;PCM&#xff09;ADC受到了制造工艺的限制&#xff0c;无法达到很高的分辨率。但基于Delta-Sigma调制技术的ADC可以在现有工艺…

无载波幅度和相位调制(CAP)与QAM调制的详细解析(可见光通信应用场景),以及CAP matlab程序下载链接

文章目录前言一、QAM调制&#xff1f;二、无载波幅度和相位调制&#xff08;CAP)三、CAP调制与QAM调制之间的联系&#xff08;异同点&#xff09;四、CAP调制相比于QAM调制的优缺点4.1、优点4.2、缺点五、无载波幅度和相位调制matlab程序五、Reference前言 目前的通信系统中&a…

jpa 事务嵌套事务_JPA 2 | EntityManagers,事务及其周围的一切

jpa 事务嵌套事务介绍 对我来说&#xff0c;最令人困惑和不清楚的事情之一是&#xff0c;作为Java开发人员&#xff0c;一直是围绕事务管理的谜团&#xff0c;尤其是JPA如何处理事务管理。 事务什么时候开始&#xff0c;什么时候结束&#xff0c;实体的持久化方式&#xff0c;持…

Matlab中装载和存储实验数据的操作

一、装载实验数据 例如&#xff0c;以下程序&#xff0c;其中path是路径&#xff0c;strcat函数将后面的参数组合成一个字符串。load函数将由twoband_CAP4_400MBd_2000MSa_float_字符串与Tx.txt构成的: twoband_CAP4_400MBd_2000MSa_float_Tx.txt文件读取至matlab中。 numSam…

无服务器革命:好,坏和丑

“这是愚蠢的。 比愚蠢还糟&#xff1a;这是一场营销炒作。” ‐ 理查德斯托曼 &#xff08; Richard Stallman&#xff09;对云计算的评论&#xff0c;2008年9月 而且&#xff0c;十年后&#xff0c;当有人提到这个词时&#xff0c;您开始三思而后行&#xff1a;是到天上掉的…

MATLAB中,信号的频谱图该怎么绘制?横坐标如何标注出频率值?

一、什么是频谱&#xff1f; 频谱的全称是频率谱密度。在对时域信号进行认识和研究的过程中非常不便&#xff0c;那我们该如何更直观地认识信号&#xff0c;更清楚地了解信号的特点呢&#xff1f; 利用傅里叶变换将时域信号变换到频域。 我们知道&#xff0c;在通信领域里傅…

Verilog HDL中模块参数传递的方法

文章目录前言一、参数传递二、参数传递方法1.方法一2.方法二3.方法三总结前言 “parameter”是Verilog HDL中的一个关键字&#xff0c;代表着参数型常量&#xff0c;即用parameter来定义一个标识符代表一个常量&#xff0c;这样可以提高程序的可读性与可维护性。 例如&#xf…

仔细看看_仔细看看,您会发现需要改进的地方

仔细看看我建议您做一个练习&#xff1a;明天早上返回工作时&#xff0c;浏览项目的源代码&#xff0c;并尝试寻找重构的机会。 即使老板没有要求也要这样做。 这样做是因为您想要一些激动人心的工作时间。 重构是改变已经可以正常工作的艺术 。 但是要进行重构&#xff0c;您…

Verilog HDL中位运算符、逻辑运算符和缩减运算符的区别

文章目录前言一、单目运算符、双目运算符和三目运算符二、位运算符三、逻辑运算符四、缩减运算符五、总结前言 我们在学习和理解Verilog HDL中的一些运算符的意义时&#xff0c;可能会对一些运算符的使用产生混乱&#xff0c;因此本文整理了Verilog HDL中&与&&、|…

Verilog HDL中容易生成锁存器的两种情况

在Verilog HDL的程序设计中&#xff0c;有两种情况会生成锁存器。 第一种情况 在always块中使用if语句&#xff0c;但是没有else&#xff0c;这会导致当条件不成立时&#xff0c;没有其他语句可执行&#xff0c;使得被赋值的寄存器一直保持不变&#xff0c;”锁存“住。 第二…