欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文詳解Spring任務執(zhí)行和調度(小結)

 更新時間:2019年08月21日 16:41:51   作者:本人禿頂程序員  
這篇文章主要介紹了一文詳解Spring任務執(zhí)行和調度(小結),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

一、概述

Spring框架分別使用TaskExecutor和TaskScheduler接口提供異步執(zhí)行和任務調度的抽象。Spring還提供了這些接口的實現(xiàn),這些接口支持線程池或將其委托給應用服務器環(huán)境中的CommonJ。

二、TaskExecutor

Spring 2.0 開始引入的新的抽像。Executors 是線程池的Java 5名稱。之所以稱作是“執(zhí)行器”是因為不能保證底層實現(xiàn)實際上是一個池;執(zhí)行程序可以是單線程的,甚至是同步的。Spring的TaskExecutor接口與java.util.concurrent是等價的。

2.1 TaskExecutor類型

SimpleAsyncTaskExecutor

線程不會重用,每次調用開啟一個新的線程。支持并發(fā),超過最大并發(fā)調用數(shù)時,會阻塞,直到釋放一個槽為止。

SyncTaskExecutor

不會異步執(zhí)行調用。每次調用都發(fā)生在調用線程中。它主要用于不需要多線程的情況。

ConcurrentTaskExecutor

Java 5 Java .util.concurrent. executor的包裝。替代方案是ThreadPoolTaskExecutor,它將Executor配置參數(shù)作為bean屬性公開。很少使用。

SimpleThreadPoolTaskExecutor

Quartz的SimpleThreadPool的一個子類,它監(jiān)聽Spring的生命周期回調。Quartz組件和非Quartz組件共享需要共享一個線程池時,通常會使用這種方法。

ThreadPoolTaskExecutor

只能在java5中使用。公開了用于配置java.util.concurrent的bean屬性。如果需要高級的東西,比如ScheduledThreadPoolExecutor,建議使用ConcurrentTaskExecutor替代。

TimerTaskExecutor

通過TimerTask支撐實現(xiàn)。 不同于SyncTaskExecutor,因為方法調用在一個單獨的線程中執(zhí)行,盡管它們在那個線程中是同步的。

WorkManagerTaskExecutor

使用CommonJ WorkManager作為它的支持實現(xiàn),并且是在Spring上下文中設置CommonJ WorkManager引用的中心便利類。與SimpleThreadPoolTaskExecutor類似,這個類實現(xiàn)了WorkManager接口,因此也可以直接作為WorkManager使用。

2.2 使用 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));
  }
 }
}

與其從池中檢索線程并自己執(zhí)行,不如將Runnable添加到隊列中,而TaskExecutor使用其內部規(guī)則來決定任務何時執(zhí)行

配置TaskExecutor將使用的規(guī)則

<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="cn.pconline.activity.task.TaskExecutorExample" init-method="printMessages">
<constructor-arg ref="taskExecutor" />
</bean>

三、TaskScheduler

除了任務執(zhí)行者抽象之外。Spring 3.0還引入了一個TaskScheduler,它有多種方法來調度未來某個時候運行的任務。

public interface TaskScheduler {
 ScheduledFuture schedule(Runnable task, Trigger trigger);
 ScheduledFuture schedule(Runnable task, Date startTime);
 ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);
 ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
 ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
 ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
}

名為“schedule”的方法,它只接受可運行的日期。這將導致任務在指定時間后運行一次。

所有其他方法都能夠安排任務重復運行。固定速率和固定延遲方法用于簡單的、周期性的執(zhí)行,但是使用 Trigger 的方法要靈活得多。

3.1 Trigger

觸發(fā)器的基本思想是,執(zhí)行時間可以根據(jù)過去的執(zhí)行結果甚至任意條件來確定。如果這些決定確實考慮了前面執(zhí)行的結果,那么該信息在TriggerContext中是可用的。

public interface Trigger {
 Date nextExecutionTime(TriggerContext triggerContext);
}
public interface TriggerContext {
 Date lastScheduledExecutionTime();
 Date lastActualExecutionTime();
 Date lastCompletionTime();
}

TriggerContext是最重要的部分。它封裝了所有相關的數(shù)據(jù),如果有必要,將來還可以進行擴展。TriggerContext是一個接口(默認情況下使用SimpleTriggerContext實現(xiàn))。

3.2 Trigger 實現(xiàn)

Spring提供了觸發(fā)器接口的兩個實現(xiàn)。最有趣的是CronTrigger。它支持基于cron表達式的任務調度。

scheduler.schedule(task, new CronTrigger(" 15 9-17 * MON-FRI"));

另一個開箱即用的實現(xiàn)是一個周期性Trigger ,它接受一個固定的周期、一個可選的初始延遲值,以及一個布爾值,用來指示周期應該解釋為固定速率還是固定延遲。由于TaskScheduler接口已經定義了以固定速率或固定延遲調度任務的方法,因此應該盡可能直接使用這些方法。PeriodicTrigger實現(xiàn)的價值在于它可以在依賴于觸發(fā)器抽象的組件中使用。例如,允許周期性Trigger 、基于cro的Trigger ,甚至自定義Trigger 實現(xiàn)可以互換使用,這可能很方便。這樣的組件可以利用依賴注入,這樣就可以在外部配置這樣的Trigger 。

3.3 TaskScheduler實現(xiàn)

在應用服務器環(huán)境中,TaskScheduler提供的靈活性尤其重要。因為在這種環(huán)境中,線程不應該由應用程序本身直接創(chuàng)建。對于這種情況,Spring提供了一個TimerManagerTaskScheduler,它將委托給CommonJ TimerManager實例,通常配置為JNDI-lookup。

四、調度和異步執(zhí)行的注解支持

4.1 開啟scheduling 注解功能

為了支持@Scheduled和@Async注釋,請將@EnableScheduling和@EnableAsync添加到@Configuration類中

@Configuration
@EnableAsync
@EnableSCheduling
public class AppConfig {
}

你可以自由選擇應用程序的相關注釋。例如,如果只需要支持@Scheduled,那么只需省略@EnableAsync即可。對于更細粒度的控制,可以另外實現(xiàn)調度器和/或AsyncConfigurer接口。

如果你更喜歡xml配置,這樣配置。

<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>}

4.2 @Scheduled

@Scheduled添加到方法上

//上一次調用完之后,五秒再調用一次,依此循環(huán)下去
@Scheduled(fixedDelay=5000)
public void doSomething() {
 // something that should execute periodically
}
//連續(xù)的每次調用開始時間之間,間隔5s
@Scheduled(fixedRate=5000)
public void doSomething() {
 // something that should execute periodically
}
//
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
 // something that should execute on weekdays only
}

值得注意的是調度的方法返回值必須是void,并且不能期望有任何參數(shù)。如果方法需要與來自應用程序上下文的其他對象交互,那么這些對象通常是通過依賴注入提供的。

4.3 @Async注解

添加了@Async注解的方法會異步執(zhí)行。換句話說,方法調用后會立即返回,方法的實際執(zhí)行將發(fā)生在提交給Spring TaskExecutor的任務中。

@Async
void doSomething() {
 // this will be executed asynchronously
}
/@Scheduled注釋的方法不同,這些方法可以預期參數(shù).
//因為調用方將在運行時以“正常”方式調用它們,而不是從容器管理的調度任務中調用。
@Async
void doSomething(String s) {
 // this will be executed asynchronously
}
// 具有Future回調返回值
//執(zhí)行其它任務的優(yōu)先級 依然是高于執(zhí)行回調的優(yōu)先級。
@Async
Future<String> returnSomething(int i) {
 // this will be executed asynchronously
}


4.4 指定@Async注解的執(zhí)行器

默認情況下,在方法上指定@Async時,將使用的執(zhí)行器是提供“annotation-driven”元素的執(zhí)行器,如上所述。然而,當需要指示在執(zhí)行給定方法時應該使用非默認的執(zhí)行器時,可以使用@Async注釋的值屬性。

@Async("otherExecutor")
void doSomething(String s) {
 // this will be executed asynchronously by "otherExecutor"
}

五、Task 命名空間

從Spring 3.0開始,有一個用于配置TaskExecutor和TaskScheduler實例的XML名稱空間。并提供了一種方便的方法,可以將任務配置為使用觸發(fā)器進行調度。

5.1 scheduler 元素

<!-- 默認創(chuàng)建一個指定大小的ThreadPoolTaskScheduler -->
<task:scheduler id="scheduler" pool-size="10"/>

id屬性用作線程池中線程的前綴名。如果不指定pool-size,默認的線程池中只有一個線程。

5.2 executor元素

<!-- 創(chuàng)建ThreadPoolTaskExecutor實例 -->
<task:executor id="executor" pool-size="10"/>

與上面的調度器一樣,為'id'屬性提供的值將用作池中線程名稱的前綴。就池大小而言,'executor'元素比'scheduler'元素支持更多的配置選項。首先,ThreadPoolTaskExecutor的線程池本身是可配置的。執(zhí)行程序的線程池可能對核心和最大大小有不同的值,而不僅僅是單個大小。如果提供了單個值,那么執(zhí)行器將擁有一個固定大小的線程池(核心和最大大小相同)。然而,“executor”元素的“池大小”屬性也接受“min-max”形式的范圍。

<task:executor id="executorWithPoolSizeRange"
pool-size="5-25"
queue-capacity="100"/><!-- 指定隊列的大小-->
<task:executor id="executorWithCallerRunsPolicy"
pool-size="5-25"
queue-capacity="100"
rejection-policy="CALLER_RUNS"/><!-- 任務拒絕策略(強制任務提交線程執(zhí)行任務,從而限制傳入負載變得過大) 默認的是直接拋出異常-->

5.3 scheduled-tasks元素

Spring task namespace 最強大的特性是支持在Spring應用程序上下文中配置要調度的任務。這與Spring中的其他“方法調用者”類似,例如JMS名稱空間提供的配置消息驅動pojo的方法。

<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="beanA" method="methodA" fixed-delay="5000"/><!--ref
指向容器管理的對象,method是要執(zhí)行的方法名-->
</task:scheduled-tasks>
<task:scheduler id="myScheduler" pool-size="10"/>
<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="beanA" method="methodA" fixed-delay="5000" initial-delay="1000"/><!--第一次執(zhí)行延遲一秒,以后每次上一個任務完成后 再執(zhí)行-->
<task:scheduled ref="beanB" method="methodB" fixed-rate="5000"/>
<!--固定頻率執(zhí)行 如果上一個任務執(zhí)行時間超時,第二個任務會立即執(zhí)行 -->
<task:scheduled ref="beanC" method="methodC" cron="*/5 * * * * MON-FRI"/>
</task:scheduled-tasks>
<task:scheduler id="myScheduler" pool-size="10"/>

六、Quartz Scheduler

Quartz使用觸發(fā)器、作業(yè)和作業(yè)細節(jié)對象來實現(xiàn)各種作業(yè)的調度。有關Quartz背后的基本概念,請參閱http://quartz-scheduling er.org。為了方便起見,Spring提供了兩個類,它們簡化了基于Spring的應用程序中Quartz的使用。

6.1 使用JobDetailBean

JobDetail對象包含運行作業(yè)所需的所有信息。Spring框架提供了JobDetailBean,它使JobDetail更接近于具有合理默認值的實際JavaBean。

<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 具有運行作業(yè)(ExampleJob)所需的所有信息。timeout在job data map指定。job data map可以通過JobExecutionContext(在執(zhí)行時傳遞給您)獲得,但是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
 }
}

6.2 使用MethodInvokingJobDetailFactoryBean

使用MethodInvokingJobDetailFactoryBean你可以調用特定對象上的方法。

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

使用上面的配置將會導致ExampleBusinessObject .doIt()方法被調用。

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

使用MethodInvokingJobDetailFactoryBean,不再需要創(chuàng)建只調用一個方法的一行作業(yè),只需要創(chuàng)建實際的業(yè)務對象并連接到它。

默認情況下,Quartz作業(yè)是無狀態(tài)的,導致作業(yè)相互干擾的可能性。如果為相同的JobDetail指定兩個觸發(fā)器,那么可能在第一個作業(yè)完成之前,第二個作業(yè)就會開始。如果JobDetail類實現(xiàn)有狀態(tài)接口,則不會發(fā)生這種情況。在第一項工作完成之前,第二項工作不會開始。要使方法調用jobdetailfactorybean產生的作業(yè)非并發(fā),請將并發(fā)標志設置為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" />
<!--并發(fā)執(zhí)行false-->
</bean>

6.3 作業(yè)調度

盡管我們能使用MethodInvokingJobDetailFactoryBean調用特定對象上的方法,但是我們還是需要調度作業(yè) 。這需要使用觸發(fā)器和scheduler erfactorybean完成。Quartz 提供了多種觸發(fā)器

Spring提供了兩種Quartz 工廠對象:

  • CronTriggerFactoryBean
  • SimpleTriggerFactoryBean

兩種觸發(fā)器的示例

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz
.SimpleTriggerFactoryBean">
<!-- 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
.CronTriggerFactoryBean">
<property name="jobDetail" ref="exampleJob" />
<!-- run every morning at 6 AM -->
<property name="cronExpression" value="0 0 6 * * ?" />
<!-- 每天早上六點執(zhí)行-->
</bean>

關于SchedulerFactoryBean的等多屬性設置 ,參考SchedulerFactoryBean javadoc

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • mybatis-plus主鍵id生成、字段自動填充的實現(xiàn)代碼

    mybatis-plus主鍵id生成、字段自動填充的實現(xiàn)代碼

    這篇文章主要介紹了mybatis-plus主鍵id生成、字段自動填充的實現(xiàn)代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Java多線程的調度_動力節(jié)點Java學院整理

    Java多線程的調度_動力節(jié)點Java學院整理

    有多個線程,如何控制它們執(zhí)行的先后次序呢?下文給大家分享四種方法及java多線程調度的實例代碼,需要的朋友參考下吧
    2017-05-05
  • 快速學習JavaWeb中監(jiān)聽器(Listener)的使用方法

    快速學習JavaWeb中監(jiān)聽器(Listener)的使用方法

    這篇文章主要幫助大家快速學習JavaWeb中監(jiān)聽器(Listener)的使用方法,感興趣的小伙伴們可以參考一下
    2016-09-09
  • SpringBoot使用Redis的zset統(tǒng)計在線用戶信息

    SpringBoot使用Redis的zset統(tǒng)計在線用戶信息

    這篇文章主要介紹了SpringBoot使用Redis的zset統(tǒng)計在線用戶信息,幫助大家更好的理解和學習使用SpringBoot框架,感興趣的朋友可以了解下
    2021-04-04
  • JAVA找不到符號的三種解決方案

    JAVA找不到符號的三種解決方案

    這篇文章主要給大家介紹了關于JAVA找不到符號的三種解決方案, 找不到符號錯誤主要發(fā)生在我們試圖引用一個未在我們正在編譯的程序中聲明的變量時,這意味著編譯器不知道我們所引用的Java變量,需要的朋友可以參考下
    2024-03-03
  • java高級用法之注解和反射講義

    java高級用法之注解和反射講義

    這篇文章主要給大家介紹了關于java高級用法之注解和反射講義的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • Java 內置Http Server構建web應用案例詳解

    Java 內置Http Server構建web應用案例詳解

    這篇文章主要介紹了Java 內置Http Server構建web應用案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-09-09
  • SpringBoot登錄攔截配置詳解(實測可用)

    SpringBoot登錄攔截配置詳解(實測可用)

    這篇文章主要介紹了SpringBoot登錄攔截配置詳解(實測可用),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • 通過入門demo簡單了解netty使用方法

    通過入門demo簡單了解netty使用方法

    這篇文章主要介紹了通過入門demo簡單了解netty使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • Java中字符串中連續(xù)相同字符去重方法

    Java中字符串中連續(xù)相同字符去重方法

    今天小編就為大家分享一篇Java中字符串中連續(xù)相同字符去重方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07

最新評論