`
云哥民工
  • 浏览: 4908 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

java中定时JOB的实现方式

阅读更多

Chapter 23. Spring中的定时调度(Scheduling)和线程池(Thread Pooling)

23.1. 简介

Spring包含了对定时调度服务的内置支持类。当前,Spring支持从JDK1.3开始内置的Timer类和Quartz Scheduler(http://www.opensymphony.com/quartz/)。二者都可以通过FactoryBean,分别指向TimerTrigger实例的引用进行配置。更进一步,有个对Quartz Scheduler和Timer都有效的工具类可以让你调用某个目标对象的方法(类似通常的MethodInvokingFactoryBean操作)。Spring 还包含有用于线程池调度的类,它针对Java 1.3,1.4,5和JEE环境的差异都进行了抽象。

23.2. 使用OpenSymphony Quartz 调度器

Quartz使用Trigger, Job以及JobDetail等对象来进行各种类型的任务调度。关于Quartz的基本概念,请参阅http://www.opensymphony.com/quartz。为了让基于Spring的应用程序方便使用,Spring提供了一些类来简化uartz的用法。

23.2.1. 使用JobDetailBean

JobDetail 对象保存运行一个任务所需的全部信息。Spring提供一个叫作JobDetailBean的类让JobDetail能对一些有意义的初始值进行初始化。让我们来看个例子:

<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean">   <property name="jobClass" value="example.ExampleJob" />   <property name="jobDataAsMap">     <map>       <entry key="timeout" value="5" />     </map>   </property></bean>

Job detail bean拥有所有运行job(ExampleJob)的必要信息。通过job的data map来制定timeout。Job的data map可以通过JobExecutionContext(在运行时刻传递给你)来得到,但是JobDetailBean同时把从job的data map中得到的属性映射到实际job中的属性中去。 所以,如果ExampleJob中包含一个名为timeout的属性,JobDetailBean将自动为它赋值:

package example;public class ExampleJob extends QuartzJobBean {   private int timeout;      /**    * Setter called after the ExampleJob is instantiated    * with the value from the JobDetailBean (5)    */    public void setTimeout(int timeout) {     this.timeout = timeout;   }      protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {      // do the actual work   }}

当然,你同样可以对Job detail bean中所有其他的额外配置进行设置。

注意:使用namegroup属性,你可以分别修改job在哪一个组下运行和使用什么名称。 默认情况下,job的名称等于job detail bean的名称(在上面的例子中为exampleJob)。

 

 

 

23.2.2. 使用 MethodInvokingJobDetailFactoryBean

 

通常情况下,你只需要调用特定对象上的一个方法即可实现任务调度。你可以使用MethodInvokingJobDetailFactoryBean准确的做到这一点:

<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">   <property name="targetObject" ref="exampleBusinessObject" />   <property name="targetMethod" value="doIt" /></bean>

上面例子将调用exampleBusinessObject中的doIt方法(如下):

public class ExampleBusinessObject {     // properties and collaborators      public void doIt() {    // do the actual work   }}
<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/>

使用MethodInvokingJobDetailFactoryBean你不需要创建只有一行代码且只调用一个方法的job, 你只需要创建真实的业务对象来包装具体的细节的对象。

默认情况下,Quartz Jobs是无状态的,可能导致jobs之间互相的影响。如果你为相同的JobDetail指定两个Trigger, 很可能当第一个job完成之前,第二个job就开始了。如果JobDetail对象实现了Stateful接口,就不会发生这样的事情。 第二个job将不会在第一个job完成之前开始。为了使得jobs不并发运行,设置MethodInvokingJobDetailFactoryBean中的concurrent标记为false

<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">   <property name="targetObject" ref="exampleBusinessObject" />   <property name="targetMethod" value="doIt" />   <property name="concurrent" value="false" /></bean>
Note
[Note]

注意:默认情况下,jobs在并行的方式下运行。

 

 

 

 

23.2.3. 使用triggers和SchedulerFactoryBean来包装任务

我们已经创建了job details,jobs。我们同时回顾了允许你调用特定对象上某一个方法的便捷的bean。 当然我们仍需要调度这些jobs。这需要使用triggers和SchedulerFactoryBean来完成。 Quartz自带一些可供使用的triggers。Spring提供两个子类triggers,分别为CronTriggerBeanSimpleTriggerBean

Triggers也需要被调度。Spring提供SchedulerFactoryBean来暴露一些属性来设置triggers。SchedulerFactoryBean负责调度那些实际的triggers。

几个例子:

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">     <!-- see the example of method invoking job above -->     <property name="jobDetail" ref="jobDetail" />     <!-- 10 seconds -->     <property name="startDelay" value="10000" />     <!-- repeat every 50 seconds -->     <property name="repeatInterval" value="50000" /></bean><bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">     <property name="jobDetail" ref="exampleJob" />     <!-- run every morning at 6 AM -->     <property name="cronExpression" value="0 0 6 * * ?" /></bean>

现在我们创建了两个triggers,其中一个开始延迟10秒以后每50秒运行一次,另一个每天早上6点钟运行。 我们需要创建一个SchedulerFactoryBean来最终实现上述的一切:

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">     <property name="triggers">         <list>             <ref bean="cronTrigger" />             <ref bean="simpleTrigger" />         </list>     </property></bean>

更多的属性你可以通过SchedulerFactoryBean来设置,例如job details使用的Calendars, 用来订制Quartz的一些属性以及其它相关信息。 你可以查阅相应的JavaDOC(http://www.springframework.org/docs/api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html)来了解进一步的信息。

 

 

 

23.3. 使用JDK Timer支持类

另外一个调度任务的途径是使用JDK Timer对象。更多的关于Timer的信息可以在这里http://java.sun.com/docs/books/tutorial/essential/threads/timer.html找到。 上面讨论的概念仍可以应用于Timer的支持。你可以创建定制的timer或者调用某些方法的timer。包装timers的工作由TimerFactoryBean完成。

23.3.1. 创建定制的timers

你可以使用TimerTask创建定制的timer tasks,类似于Quartz中的jobs:

public class CheckEmailAddresses extends TimerTask {   private List emailAddresses;      public void setEmailAddresses(List emailAddresses) {     this.emailAddresses = emailAddresses;   }      public void run() {    // iterate over all email addresses and archive them   }}

包装它很简单:

<bean id="checkEmail" class="examples.CheckEmailAddress">     <property name="emailAddresses">         <list>             <value>test@springframework.org</value>             <value>foo@bar.com</value>             <value>john@doe.net</value>         </list>     </property></bean><bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">    <!-- wait 10 seconds before starting repeated execution -->     <property name="delay" value="10000" />    <!-- run every 50 seconds -->     <property name="period" value="50000" />     <property name="timerTask" ref="checkEmail" /></bean>

注意若要让任务只运行一次,你可以把period属性设置为0(或者负值)。

23.3.2. 使用MethodInvokingTimerTaskFactoryBean

和对Quartz的支持类似,对Timer的支持也包含一个组件,可以让你周期性的调用某个方法:

<bean id="doIt" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">     <property name="targetObject" ref="exampleBusinessObject" />     <property name="targetMethod" value="doIt" /></bean>

以上的例子会调用exampleBusinessObject对象的doIt方法。(见下):

public class BusinessObject {     // properties and collaborators      public void doIt() {    // do the actual work   }}

将上例中ScheduledTimerTasktimerTask引用修改为doIt,bean将会用一个固定的周期来调用doIt方法。

 

 

23.3.3. 打包:使用TimerFactoryBean来设置任务

TimerFactoryBean类和Quartz的SchedulerFactoryBean类有些类似,它们是为同样的目的而设计的:设置确切的任务计划。TimerFactoryBean对一个Timer进行配置,设置其引用的任务的周期。你可以指定是否使用背景线程。

<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">     <property name="scheduledTimerTasks">         <list>            <!-- see the example above -->             <ref bean="scheduledTask" />         </list>     </property></bean>

 

23.4. SpringTaskExecutor抽象

Spring 2.0 为执行器(Executor)处理引入了一个新的抽象层。Executor是Java 5的名词,用来表示线程池的概念。之所以用这个奇怪的名词,是因为实际上不能保证底层实现的确是一个池。实际上,很多情况下,executor只是单线程。Spring的抽象层帮助你把线程池引入到Java 1.3和1.4环境中,同时隐藏了 1.3, 1.4, 5, 和 Java EE环境中线程池实现的差异。

23.4.1. TaskExecutor接口

Spring的TaskExecutor接口等同于java.util.concurrent.Executor接口。实际上,它存在主要原因是为了在使用线程池的时候,将对Java 5的依赖抽象掉。这个接口只有一个方法execute(Runnable task),它根据线程池的语义和配置,来接受一个执行任务。

23.4.2. 何时使用TaskExecutor接口

TaskExecutor接口开始的时候,是为了其他Spring组件使用线程池的抽象需要创建的。例如ApplicationEventMulticaster组件、JMS的 AbstractMessageListenerContainer和对Quartz的整合都使用了TaskExecutor接口来抽象线程池。当然,如果你的bean需要线程池行为,你也可以使用这个抽象层。

23.4.3. TaskExecutor类型

在Spring发行包中预定义了一些TaskExecutor实现。有了它们,你甚至不需要再自行实现了。

  • SimpleAsyncTaskExecutor

    这个实现不重用任何线程,或者说它每次调用都启动一个新线程。但是,它还是支持对并发总数设限,当超过线程并发总数限制时,阻塞新的调用,直到有位置被释放。如果你需要真正的池,请继续往下看。

  • SyncTaskExecutor

    这个实现不会异步执行。相反,每次调用都在发起调用的线程中执行。它的主要用处是在不需要多线程的时候,比如简单的test case。

  • ConcurrentTaskExecutor

    这个实现是对Java 5 java.util.concurrent.Executor类的包装。有另一个备选, ThreadPoolTaskExecutor类,它暴露了Executor的配置参数作为bean属性。很少需要使用ConcurrentTaskExecutor, 但是如果ThreadPoolTaskExecutor不敷所需,ConcurrentTaskExecutor是另外一个备选。

  • SimpleThreadPoolTaskExecutor

    这个实现实际上是Quartz的SimpleThreadPool类的子类,它会监听Spring的生命周期回调。当你有线程池,需要在Quartz和非Quartz组件中共用时,这是它的典型用处。

  • ThreadPoolTaskExecutor

    它不支持任何对java.util.concurrent包的替换或者下行移植。Doug Lea和Dawid Kurzyniec对java.util.concurrent的实现都采用了不同的包结构,导致它们无法正确运行。

    这个实现只能在Java 5环境中使用,但是却是这个环境中最常用的。它暴露的bean properties可以用来配置一个java.util.concurrent.ThreadPoolExecutor,把它包装到一个TaskExecutor中。如果你需要更加先进的类,比如ScheduledThreadPoolExecutor,我们建议你使用ConcurrentTaskExecutor来替代。

  • TimerTaskExecutor

    这个实现使用一个TimerTask作为其背后的实现。它和SyncTaskExecutor的不同在于,方法调用是在一个独立的线程中进行的,虽然在那个线程中是同步的。

  • WorkManagerTaskExecutor

    CommonJ 是BEA和IBM联合开发的一套规范。这些规范并非Java EE的标准,但它是BEA和IBM的应用服务器实现的共同标准

    这个实现使用了CommonJ WorkManager作为其底层实现,是在Spring context中配置CommonJ WorkManager应用的最重要的类。和SimpleThreadPoolTaskExecutor类似,这个类实现了WorkManager接口,因此可以直接作为WorkManager使用。 

23.4.4. 使用TaskExecutor接口

Spring的TaskExecutor实现作为一个简单的JavaBeans使用。在下面的示例中,我们定义一个bean,使用 ThreadPoolTaskExecutor来异步打印出一系列字符串。

import org.springframework.core.task.TaskExecutor;public class TaskExecutorExample {   private class MessagePrinterTask implements Runnable {     private String message;     public MessagePrinterTask(String message) {       this.message = message;     }     public void run() {       System.out.println(message);     }   }   private TaskExecutor taskExecutor;   public TaskExecutorExample(TaskExecutor taskExecutor) {     this.taskExecutor = taskExecutor;   }   public void printMessages() {     for(int i = 0; i < 25; i++) {       taskExecutor.execute(new MessagePrinterTask("Message" + i));     }   }}

可以看到,无需你自己从池中获取一个线程来执行,你把自己的Runnable类加入到队列中去,TaskExecutor使用它自己的内置规则来决定何时应该执行任务。

为了配置TaskExecutor使用的规则,暴露了简单的bean properties。

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">   <property name="corePoolSize" value="5" />   <property name="maxPoolSize" value="10" />   <property name="queueCapacity" value="25" /></bean><bean id="taskExecutorExample" class="TaskExecutorExample">   <constructor-arg ref="taskExecutor" /></bean>

 

 

分享到:
评论

相关推荐

    java定时任务JOB任务设置

    java定时任务JOB任务设置java定时任务JOB任务设置java定时任务JOB任务设置

    java动态管理定时任务

    在Java开发中,定时任务是不可或缺的一部分,尤其在企业级应用中,用于执行定期的数据处理、报表生成、系统维护等工作。Spring框架与Quartz库的整合提供了强大的动态管理定时任务的能力。下面我们将深入探讨这个主题...

    Java分布式Elastic-Job和Quartz定时任务课程(1.6G)

    18_Simple作业的3种整合方式介绍.mp4 19_Spring整合Simple作业-上.mp4 20_Spring整合Simple作业-下.mp4 21_Java_API整合Simple作业.mp4 22_Spring_Boot整合Simple作业-1.mp4 23_Spring_Boot整合Simple作业-2.mp4 24_...

    java 定时备份数据库

    总之,实现Java定时备份MySQL数据库需要理解如何在Java中调用外部命令,如何创建定时任务,以及如何与Spring等框架集成。在SSM项目中,可以利用Spring的定时任务特性来优雅地管理备份任务。记得在实际应用中处理异常...

    定时调度器 xxl-job

    xxl-job是一款基于Java实现的分布式任务调度平台,它提供了简单易用的API和管理界面,使得开发者能够轻松地实现任务的定时调度。在这个压缩包中,你将找到xxl-job的核心组件——xxl-job-admin以及一个执行器的示例...

    java quartz 定时任务

    在Java中,可以使用ScheduledExecutorService或者Quartz来实现定时任务。 3. **Cron表达式**: - Cron表达式是Unix cron服务的一种时间格式,用于定义任务的执行时间。它由7个子字段组成(秒、分钟、小时、日期、...

    java定时任务quartz的基本实现

    Java定时任务在软件开发中扮演着重要角色,它允许开发者安排任务在特定时间执行,而无需持续监控。Quartz是Java领域中一个广泛使用的开源任务调度框架,它提供了丰富的功能来满足各种定时任务的需求。本篇文章将深入...

    java定时生成execl并发送邮件

    在Java编程领域,实现“java定时生成execl并发送邮件”的功能是一项常见的需求,尤其在自动化运维、数据报告和监控系统中。这个功能涉及到多个Java库和技术,包括Apache POI用于处理Excel文件,Quartz作为定时任务...

    java定时任务调度

    Java定时任务调度是Java开发中常见的一种功能,用于在特定时间执行特定的任务,例如数据同步、日志清理、报表生成等。在Java中,有多种实现定时任务调度的方式,包括但不限于Java内置的`java.util.Timer`类、Spring...

    基于Java实现的xxl-job定时任务及管理后台前端源码

    该项目是一款基于Java的xxl-job定时任务管理系统前端源码,包含288个文件,其中Java源文件134个,JavaScript脚本35个,CSS样式表12个,以及其他类型的文件如PNG图片、XML配置、FTL模板、属性文件等。项目启动后可...

    k8s+springboot+cronjob 定时任务配置

    总结来说,将 Spring Boot 与 Kubernetes CronJob 结合使用,可以在云环境中实现高效且灵活的定时任务管理。开发者只需要关注业务逻辑,而 Kubernetes 负责管理和调度这些任务,极大地提高了系统的可扩展性和可靠性...

    Java使用quartz实现任务调度定时任务

    本篇文章将深入探讨如何使用Quartz在Java应用程序中实现任务调度。 Quartz库提供了一个灵活的API,可以创建、调度和管理任务,这些任务被称为Job。每个Job都与一个Trigger关联,Trigger定义了何时启动Job。在Java...

    java定时任务

    下面我们将深入探讨Java定时任务的实现方式以及这两个文件可能涉及的概念。 1. **Java定时任务框架** Java提供了一些内置的API来创建定时任务,如`java.util.Timer`和`java.util.concurrent....

    java job_触发器例子

    Java Job和触发器是Java应用程序中用于定时任务处理的关键组件,尤其在企业级应用和大数据处理中非常常见。本文将深入探讨Java中的Job和触发器,以及如何通过示例进行应用。 首先,让我们理解什么是Java Job。在...

    java spring quartz 动态定时任务

    要实现Java Spring Quartz动态定时任务,首先需要在项目中引入Quartz库,通常通过Maven或Gradle添加依赖。接下来,配置Spring的ApplicationContext,声明一个SchedulerFactoryBean,它会初始化并管理Quartz的...

    java各种job

    Java中的Job是一个宽泛的概念,通常指在后台执行的任务或者定时任务。本资源包涵盖了Java基础的Job处理、Quartz框架、Spring Scheduling以及Spring与Quartz结合使用时的数据库配置,这些都是Java开发者在实现定时...

    Java语言定时调度任务之实现.pdf

    Java语言中实现定时调度任务通常有三种主流方法:Timer调度、线程池调度和Quartz调度。每种方法各有其特点和适用场景。 1. Timer调度 Timer调度是Java中最简单的定时调度实现方式。其主要特点是非常简单和直观。它...

    基于Java的xxl-job定时任务调度系统设计源码

    xxl-job是一个基于Java开发的定时任务调度系统,包含287个文件,其中包括135个Java源文件、35个PNG图片文件、35个JavaScript文件、16个XML文件、12个CSS文件、11个FTL模板文件、5个Markdown文件、4个Properties文件...

    java 定时重启服务工具

    在提供的压缩包文件中,"RbootTool.zip"可能是服务重启工具的主程序,它可能包含了实现定时任务的核心逻辑,如使用上述的Java定时机制,并且具备服务监控和重启的接口。而"TimerJob.rar"可能包含了具体的定时任务...

    基于Java实现的几种定时任务的方式

    JDK自带的Timer API算是最古老的定时任务实现方式了。Timer是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以安排任务“执行一次”或者定期“执行多次”。 使用开源的框架来实现,比如Quartz。 ...

Global site tag (gtag.js) - Google Analytics