`
AllenHU0320
  • 浏览: 85838 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring中的任务调度和线程池支持

 
阅读更多

1.Spring与Quartz

Quartz是Open Symphony开发的一款开源的任务调度框架。相对于JDK的Timer之类的简单任务调度程序来说,Quartz拥有更为全面的功能支持:

1)允许批处理任务状态的持久化,并且提供不同的持久化策略支持

2)批处理任务的远程调度

3)提供基于Web的监控接口

4)集群支持

5)插件式的可扩展性

 

2.Quartz拥有明确的角色划分,分别对应处理任务调度过程中的各种相关关注点:

1)Job:代表将要被调度的任务

2)JobDetail:主要职能是提供Job执行的上下文信息,Job所依赖的某些配置信息,可以通过JobDetail提供,二者通过JobDataMap进行数据交互

3)Trigger:用于触发被调度任务的执行,可以根据不同的触发条件,提供不同的Trigger实现

4)Scheduler:Quartz的核心调度程序,负责管理所有相关的Trgger和JobDetail

 

3.一个Trigger只能用于一个Job,但多个Trigger可以用于同一Job

Quartz中最经常使用的主要的两种Trigger实现类:

一个是SimpleTrigger,可以指定简单的基于时间间隔的调度规则

一个是CronTrigger,可以类似于Unix/Linux操作系统中Cron程序多使用的表达式来指定调度规则

 

public class FXNewsJob implements Job{

    private FXNewsProvider fxNewsProvider;

    //getXXX();

    //setXXX();

    public void execute(JobExecutionContext jobExecCtx) throws JobExecutionException{

          getFxNewsProvider().getAndPersistNews();

    }

}

 

Trigger simpleTrigger = new SimpleTrigger("triggerName",Scheduler.DEFAULT_GROUP,new Date(),null,SimpleTrigger.REPEAT_INDEFINITELY,60000);

Trigger cronTrigger = new CronTrigger("cronTriggerName",Scheduler.DEFAULT_GROUP,"0 0/1 * * * ?");

 

在Job和Trigger都具备后,通过Scheduler将它们关联起来并进行最终的任务调度

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

scheduler.start();

JobDetail jobDetail = new JobDetail("jobName",Scheduler.DEFAULT_GROUP,FXNewsJob.class);

Trigger cronTrigger = new CronTrigger("cronTriggerName",Scheduler.DEFAULT_GROUP,"0 0/1 * * * ?");

scheduler.scheduleJob(jobDetail,cronTrigger);

 

4.融入Spring大家庭的Quartz

1)Job的实现策略

在Quartz中,每一Job所需要的执行上下文(Execution Context)信息是由其对应的JobDetail提供的,二者通过JobDataMap进行数据通信

JobDetail jobDetail = new JobDetail("jobName",Scheduler.DEFAULT_GROUP,HelloWorldJob.class);

jobDetail.getJobDataMap().put("message","helloworld");

jobDetail.getJobDataMap().put("counter",10);

public class HelloWorldJob implements Job{

      public void execute(JobExecutionContext ctx) throws JobExecutionException{

            JobDataMap jobDataMap = ctx.getJobDetail().getJobDataMap();

            String message = jobDataMap.getString("message");

            int counter = jobDataMap.getInt("counter");

            //...

      }

}

Spring提供了org.springframework.scheduling.quartz.QuartzJobBean。在实现Job的时候,通过继承QuartzJobBean,让我们在Job实现类中,直接以bean属性的形式访问当前Job执行上下文信息

public class HelloWorldJobExtendingQuartzJobBean extends QuartzJobBean{

       private String message;

       private int counter;

       //getXXX();

       //setXXX();

       public void executeInternal(JobExecutionContext ctx) throws JobExecutionException{

             //getMessage()并使用

             //getCounter()并使用

       }

}

Spring提供了org.springframework.scheduling.quartz.SpringBeanJobFactory是一种更好的选择,允许对要执行的Job进行定制

2)JobDetail的更多选择

通过org.springframework.scheduling.quartz.JobDetailBean来创建和配置相应Job所对应的JobDetail实例

<bean id="fxNewsJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">

       <property name="jobClass" value="HelloWorldJob | HelloWorldJobExtendingQuartzJobBean" />

       <property name="jobDataAsMap">

              <map>

                      <entry key="message">

                             <value>HelloWorld</value>

                      </entry>

                      <entry key="counter">

                             <value>10</value>

                      </entry>

              </map>

       </property>

</bean>

一个比较优雅的MethodInvokingJobDetailFactoryBean

<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

       <property name="targetObject" ref="fxNewsProvider" />

       <property name="targetMethod" value="getAndPersistNews" />

</bean>

MethodInvokingJobDetailFactoryBean会在内部构建相应的Job实现类(MethodInvokingJob和StatefulMethodInvokingJob),这些Job实现类会在合适的时机调用指定给MethodInvokingJobDetailFactoryBean的业务对象上的业务方法。但是,通过它所返回的JobDetail信息是不可序列化的,从而也就无法保存或者说持久化。

3)Trigger的可配置化

Spring分别提供了SimpleTriggerBean和CronTrggerBean封装类,同样采用FactoryBean机制实现

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">

       <property name="jobDetail" ref="jobDetail"/>

       <property name="repeatInterval" value="3000"/>

</bean>

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTrggerBean">

        <property name="jobDetail" ref="jobDetail"/>

        <property name="cronExpression" value="0 0/1 * * * ?"/>

</bean>

可以结合Trgger与Quartz提供的Calender来达成最终所需要的调度规则。Trigger负责提供覆盖范围足够广的调度规则,而Calender负责排除这一规则范围内不需要的部分

4)Scheduler的新家

Spring提供了org.springframework.scheduling.quartz.SchedulerFactoryBean对Quartz的Scheduler进行管理

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

         <property name="triggers">

                 <ref bean="newsTrigger" />

                 <ref bean="simpleTrigger" />

         </property>

</bean>

 

FXNewsProvider相关任务调度类配置代码示例

<bean id="fxNewsProvider" class="com.xxx.news.FXNewsProvider" p:newsListener-ref="newsListener" p:newsListener-ref="newsPersister"/>

 

<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

         <property name="targetObject" ref="fxNewsProvider" />

         <property name="targetMethod" value="getAndPersistNews" />

</bean>

 

<bean id="newsTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">

         <property name="jobDetail" ref="jobDetail" />

         <property name="cronExpression" value="0 0/1 * * * ?" />

</bean>

 

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

         <property name="triggers">

                  <list>

                         <ref bean="newsTrigger"/>

                  </list>

         </property>

</bean>

 

5.Spring对JDK Timer的集成

JDK Timer小记:所有经由Timer进行调度的任务都需要继承TimerTask

public class FXNewsTimerTask extends TimerTask{

        private FXNewsProvider fxNewsProvider;

        //getXXX();

        //setXXX();

        public void run(){

              getFxNewsProvider().getAndPersistNews();

        }

}

FXNewsTimerTask task = new FXNewsTimerTask();

Timer timer = new Timer("schedulerName[optional]");

timer.schedule(task,0,60000);

1)逃离TimerTask的魔咒

<bean id="fxNewsProvider" class="com.xxx.news.FXNewsProvider" p:newListener-ref="newsListener" p:newPersistencer-ref="newsPersister">

<bean id="task" class="org.springframework.scheduling.timer.MehodInvokingTimerTaskFactoryBean">

        <property name="targetObject" ref="fxNewsProvider"/>

        <property name="targetMethod" value="getAndPersistNews"/>

</bean>

2)TimerTask的模块化封装-ScheduledTimerTask

通过一个ScheduledTimerTask将对应的TimerTask和相关的Trigger信息封装到一个可以统一管理的实体中

<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">

         <property name="timerTask" ref="task" />

         <property name="period" value="3000">

</bean>

3)Timer的新家-TimerFactoryBean

TimerFactoryBean实现代码摘录

ScheduledTimerTask[] stt = ... ;

for(ScheduledTimerTask task : stt){

        if(task.isOneTimeTask()){

               timer.schedule(task.getTimerTask(),task.getDelay());

        }else{

               if(task.isFixedRate()){

                      timer.scheduleAtFixedRate(task.getTimerTask(),task.getDelay(),task.getPeriod());

               }else{

                      timer.schedule(task.getTimerTask(),task.getDelay(),task.getPeriod());

               }

        }

}

<bean id="scheduler" class="org.springframework.scheduling.timer.TimerFactoryBean">

        <property name="scheduledTimerTasks">

               <list>

                       <ref bean="scheduledTask" />

               </list>

        </property>

</bean>

 

6.Executor的孪生兄弟TaskExecutor

Java5为我们带来了一套新的任务执行框架,以Executor为首:

public interface Executor{

      void execute(Runnable task);

}

Executor这一抽象的意义在于,可以将任务的提交(task commission)和任务的执行(task execution)策略分隔开来,解除二者之间的耦合性,以Runnable类型界定的任务提交之后,最终会以什么样的策略执行(什么时间执行,交给谁执行,等等),完全由不同的Executor实现类负责,提交任务的客户端完全可以忽略后者的实现细节。

Spring提供的TaskExecutor完成Executor同样的功能

public interface TaskExecutor{

      void execute(Runnable task);

}

 

7.可用的TaskExecutor

1)SyncTaskExecutor

提交给SyncTaskExecutor的任务将直接在当前线程中执行

public class SyncTaskExecutor implements TaskExecutor,Serializable{

      public void execute(Runnable task){

            Assert.notNull(task,"Runnable must not be null");

            task.run();

      }

}

2)SimpleAsyncTaskExecutor

提供最基本的异步执行能力,实现的方式则是为每个任务都创建新的线程

public class SimpleAsyncTaskExecutor implements TaskExecutor{

      public void execute(Runnable task){

            new Thread(task).start();

      }

}

SimpleAsyncTaskExecutor提供了相应的属性以控制创建的线程数目上限

<bean id="simpleAsyncTaskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor">

       <property name="concurrencyLimit" value="100" />

</bean>

3)ThreadPoolTaskExecutor

用线程池来管理并重用处理任务异步执行的工作线程,ThreadPoolTaskExecutor是对标准的java.util.concurrent.ThreadPoolExecutor进行了封装

Spring提供的ThreadPoolTaskExecutor一共有两个:

org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor是对java.util.concurrent.ThreadPoolExecutor进行了封装

org.springframework.scheduling.backportconcurrent.ThreadPoolTaskExecutor是对JSR-166 backport的ThreadPoolTaskExecutor进行封装

<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">

        <property name="corePoolSize" value="10">

        <property name="maxPoolSize" value="20">

        <property name="queueCapacity" value="20">

</bean>

4)ConcurrentTaskExecutor

为Java5的Executor和Spring的TaskExecutor搭建了一道桥梁。构建自己需要的Executor实例,通过Executor.newXXXThreadPool(),然后以ConcurrentTaskExecutor对其进行封装,封装后获得的ConcurrentTaskExecutor即获得响应Executor的能力。

Executor executor = Executors.newScheduledThreadPool(10);

TaskExecutor taskExecutor = new ConcurrentTaskExecutor(executor);

5)TimeTaskExecutor、SimpleThreadPoolTaskExecutor和WorkManagerTaskExecutor

都是使用特定的调度程序(Job Scheduler)来执行提交给他们的任务

public class PrototypeTimerTaskExecutor implements TaskExecutor{

       private Timer timer = new Timer();

       public void execute(final Runnable task){

             timer.schedule(new TimerTask(){ public void run(){task.run();}},new Date());

       }

}

分享到:
评论

相关推荐

    spring 任务调度

    通过深入学习Spring任务调度,开发者可以有效地管理和执行各种定时任务,提升系统的自动化水平。在实际项目中,可以根据需求的复杂程度选择使用Spring Task或是集成Quartz。同时,理解源码有助于我们更高效地利用...

    Spring3.2.6定时任务+线程池.docx

    Spring框架提供了一个强大的任务调度模块,其中包含了对线程池的支持。下面通过一个具体的示例来展示如何在Spring3.2.6中配置线程池: ```xml &lt;!-- 线程池 --&gt; &lt;bean id="taskExecutor" class="org.springframework...

    Spring实现任务调度.rar

    本资料“Spring实现任务调度”将深入探讨如何在Spring中设置和管理定时任务。 首先,我们需要理解Spring中的任务调度机制。Spring通过其`Task`模块提供了任务调度的功能,主要由两个核心组件构成:`TaskExecutor`和...

    spring分布式任务调度

    8、调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞; 9、弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务; 10、邮件报警:任务失败时支持邮件报警,支持配置多...

    在spring boot中使用java线程池ExecutorService的讲解

    2. 工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务。 3. 任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的...

    spring 任务调度实现代码例子

    下面将详细解释Spring任务调度的关键概念和实现方法。 1. **Spring Task模块** Spring Task是Spring框架内置的任务调度模块,它提供了简单的定时任务执行能力。通过使用Spring Task,我们可以轻松地在应用中添加...

    Spring基于线程池的定时任务线挰异常实践

    在Spring框架中,定时任务和线程池是两个非常重要的组件,它们可以...同时,提到了Spring MVC在Web开发中的角色,以及它如何与任务调度协同工作。理解和掌握这些知识点对于构建高效、健壮的Spring应用程序至关重要。

    spring 线程池

    1. **线程复用**:线程池中的线程被创建后不会立即销毁,而是等待新的任务到来,从而减少线程创建和销毁的开销。 2. **任务队列**:线程池内部维护一个任务队列,新提交的任务会被放入队列,等待空闲线程来处理。 3....

    基于Spring打造简单高效通用的异步任务处理系统

    总结来说,构建基于Spring的异步任务处理系统是一个综合了数据库设计、任务调度、并发执行和故障恢复的过程。通过合理的设计和配置,我们可以实现一个既高效又易于维护的异步任务处理平台,满足复杂业务场景的需求,...

    spring线程池(同步、异步).docx

    - `ThreadPoolTaskExecutor`则是异步执行器,它会将任务放入线程池中,由池中的线程异步执行。这意味着任务可能会并行运行,提高了执行效率。 四、异步执行器的特性与配置 例如`SimpleAsyncTaskExecutor`允许我们...

    Spring中定时任务

    - `ThreadPoolTaskScheduler`:Spring提供的一个默认实现,基于线程池的任务调度器,可以控制并发执行的定时任务数量。 2. **Quartz Scheduler** - Quartz是一个开源的作业调度框架,可以实现复杂的时间规则和...

    基于Spring Boot框架的任务调度系统.zip

    1. 任务调度系统能够定时或定期执行任务,支持任务的分割和并发执行,提高任务处理效率。 2. 任务状态管理任务具有多种状态(如初始、完成、处理中、错误、等待),系统能够实时监控和管理任务状态。 3. 任务重试...

    maven spring 任务调度实列

    Spring框架提供了一个强大的任务调度模块——Spring Task,也被称为Spring Batch,它支持基于时间的任务调度和基于事件的任务触发。 首先,我们需要在`pom.xml`文件中添加Spring相关的依赖。这通常包括`spring-...

    Spring提供的线程池支持[借鉴].pdf

    总的来说,Spring的线程池支持和任务调度为开发者提供了强大的工具,帮助他们构建可扩展、高性能且易于管理的企业级应用。通过`TaskExecutor`和`ThreadPoolTaskScheduler`,开发者可以在不牺牲灵活性的前提下,确保...

    JBPM3.2与Spring结合时任务调度的实现.doc

    JBPM3.2与Spring的整合主要是为了实现任务调度的功能,这在企业级应用中是非常重要的,因为它能够自动化执行定时任务,如流程启动、数据同步、报告生成等。在JBPM3.1.x版本中,通过SpringModules提供的`spring-...

    spring定时任务关键jar包(齐全)

    `spring-context-support.jar`是Spring框架对Quartz和Commons JCR等第三方调度库的支持,同时也包含Spring自己的`TaskExecutor`和`TaskScheduler`接口,用于实现异步任务和定时任务。 1. **Spring TaskExecutor**: ...

    java实现任务调度

    Java实现任务调度的过程中,涉及到的关键技术和工具包括Quartz调度器和Spring框架。Quartz是一个功能强大的开源作业调度系统,它可以用来整合到Java应用程序中,以实现作业调度的功能。Spring框架是一个广泛使用的...

    Spring定时调度简单实现源码

    在Spring框架中,定时任务调度是一项非常重要的功能,它允许我们按照预定的时间间隔执行特定的任务。这个"Spring定时调度简单实现源码"很显然是一个关于如何在Spring中配置和使用定时任务的示例代码包。下面我们将...

    schedule-job, 基于Spring Boot Quartz 的分布式任务调度系统.zip

    【标题】:基于Spring Boot和Quartz的分布式任务调度系统 在现代企业级应用中,任务调度是一项重要的功能,用于按预定的时间间隔执行特定的任务,例如数据同步、报表生成、清理过期数据等。本项目名为“schedule-...

Global site tag (gtag.js) - Google Analytics