主頁 > 知識(shí)庫 > java 中Spring task定時(shí)任務(wù)的深入理解

java 中Spring task定時(shí)任務(wù)的深入理解

熱門標(biāo)簽:潤滑油銷售電銷機(jī)器人 海外圖書館地圖標(biāo)注點(diǎn) 自繪地圖標(biāo)注數(shù)據(jù) 外呼系統(tǒng)使用方法 電銷機(jī)器人免培訓(xùn) 給地圖標(biāo)注得傭金 如何看懂地圖標(biāo)注點(diǎn) 電話機(jī)器人需要使用網(wǎng)絡(luò)嗎 南通通訊外呼系統(tǒng)產(chǎn)品介紹

java 中Spring task定時(shí)任務(wù)的深入理解

在工作中有用到spring task作為定時(shí)任務(wù)的處理,spring通過接口TaskExecutor和TaskScheduler這兩個(gè)接口的方式為異步定時(shí)任務(wù)提供了一種抽象。這就意味著spring容許你使用其他的定時(shí)任務(wù)框架,當(dāng)然spring自身也提供了一種定時(shí)任務(wù)的實(shí)現(xiàn):spring task。spring task支持線程池,可以高效處理許多不同的定時(shí)任務(wù)。同時(shí),spring還支持使用Java自帶的Timer定時(shí)器和Quartz定時(shí)框架。限于篇幅,這里將只介紹spring task的使用。

其實(shí),官方文檔已經(jīng)介紹地足夠詳細(xì),只不過都是英文版,所以為了更好地理解并使用spring task,首先會(huì)對(duì)spring task的實(shí)現(xiàn)原理做一個(gè)簡單的介紹,然后通過實(shí)際代碼演示spring task是如何使用的。這里會(huì)涉及到一個(gè)很重要的知識(shí)點(diǎn):cron表達(dá)式。

TaskExecutor和TaskScheduler

TaskExecutor是spring task的第一個(gè)抽象,它很自然讓人聯(lián)想到j(luò)dk中concurrent包下的Executor,實(shí)際上TaskExecutor就是為區(qū)別于Executor才引入的,而引入TaskExecutor的目的就是為定時(shí)任務(wù)的執(zhí)行提供線程池的支持,那么,問題來了,為什么spring不直接使用jdk自帶的Executor呢?TaskExecutor源碼如下?

public interface TaskExecutor extends Executor {
  void execute(Runnable var1);
}

那么,答案很顯然,TaskExecutor提供的線程池支持也是基于jdk自帶的Executor的。用法于Executor沒有什么不同。

TaskScheduler是spring task的第二個(gè)抽象,那么從字面的意義看,TaskScheduler就是為了提供定時(shí)任務(wù)的支持咯。TaskScheduler需要傳入一個(gè)Runnable的任務(wù)做為參數(shù),并指定需要周期執(zhí)行的時(shí)間或者觸發(fā)器,這樣Runnable任務(wù)就可以周期性執(zhí)行了。傳入時(shí)間很好理解,有意思的是傳入一個(gè)觸發(fā)器(Trigger)的情況,因?yàn)檫@里需要使用cron表達(dá)式去觸發(fā)一個(gè)定時(shí)任務(wù),所以有必要先了解下cron表達(dá)式的使用。

在spring 4.x中已經(jīng)不支持7個(gè)參數(shù)的cronin表達(dá)式了,要求必須是6個(gè)參數(shù)(具體哪個(gè)參數(shù)后面會(huì)說)。cron表達(dá)式的格式如下:

{秒} {分} {時(shí)} {日期(具體哪天)} {月} {星期}
  • 秒:必填項(xiàng),允許的值范圍是0-59,支持的特殊符號(hào)包括
  • , - * /,,表示特定的某一秒才會(huì)觸發(fā)任務(wù),-表示一段時(shí)間內(nèi)會(huì)觸發(fā)任務(wù),*表示每一秒都會(huì)觸發(fā),/表示從哪一個(gè)時(shí)刻開始,每隔多長時(shí)間觸發(fā)一次任務(wù)。
  • 分:必填項(xiàng),允許的值范圍是0-59,支持的特殊符號(hào)和秒一樣,含義類推
  • 時(shí):必填項(xiàng),允許的值范圍是0-23,支持的特殊符號(hào)和秒一樣,含義類推
  • 日期:必填項(xiàng),允許的值范圍是1-31,支持的特殊符號(hào)相比秒多了?,表示與{星期}互斥,即意味著若明確指定{星期}觸發(fā),則表示{日期}無意義,以免引起沖突和混亂。
  • 月:必填項(xiàng),允許的值范圍是1-12(JAN-DEC),支持的特殊符號(hào)與秒一樣,含義類推
  • 星期:必填項(xiàng),允許值范圍是1~7 (SUN-SAT),1代表星期天(一星期的第一天),以此類推,7代表星期六,支持的符號(hào)相比秒多了?,表達(dá)的含義是與{日期}互斥,即意味著若明確指定{日期}觸發(fā),則表示{星期}無意義。

比如下面這個(gè)cron表達(dá)式:

// 表達(dá)的含義是:每半分鐘觸發(fā)一次任務(wù)
30 * * * * ?

spring提供了一個(gè)CronTrigger,通過傳入一個(gè)Runnable任務(wù)和CronTrigger,就可以使用cron表達(dá)式去指定定時(shí)任務(wù)了,是不是非常方面。實(shí)際上,在工程實(shí)踐上,cron表達(dá)式也是使用很多的。實(shí)際上,是執(zhí)行了下面的代碼:

scheduler.schedule(task, new CronTrigger("30 * * * * ?"));

TaskScheduler抽象的好處是讓需要執(zhí)行定時(shí)任務(wù)的代碼不需要指定特定的定時(shí)框架(比如Timer和Quartz)。TaskScheduler的更簡單的實(shí)現(xiàn)是ThreadPoolTaskScheduler,它實(shí)際上代理一個(gè)jdk中的SchedulingTaskExecutor,并且也實(shí)現(xiàn)了TaskExecutor接口,所以需要經(jīng)常執(zhí)行定時(shí)任務(wù)的場景可以使用這個(gè)實(shí)現(xiàn)(Spring推薦)。我們?cè)賮砜匆幌耇askExecutor和TaskScheduler的類繼承關(guān)系:

通常而言,使用spring task實(shí)現(xiàn)定時(shí)任務(wù)有兩種方式:注解和xml配置文件。這里使用xml配置文件的方式加以說明。

實(shí)戰(zhàn)

創(chuàng)建Maven工程,pom.xml:

?xml version="1.0" encoding="UTF-8"?>
project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  modelVersion>4.0.0/modelVersion>

  groupId>com.rhwayfun/groupId>
  artifactId>sring-task-demo/artifactId>
  version>1.0-SNAPSHOT/version>

  dependencies>
    dependency>
      groupId>org.springframework/groupId>
      artifactId>spring-context/artifactId>
      version>4.2.4.RELEASE/version>
    /dependency>
  /dependencies>

  build>
    plugins>
      plugin>
        groupId>org.apache.maven.plugins/groupId>
        artifactId>maven-compiler-plugin/artifactId>
        version>3.5.1/version>
        configuration>
          source>1.8/source>
          target>1.8/target>
        /configuration>
      /plugin>
    /plugins>
  /build>
/project>

開發(fā)需要執(zhí)行定時(shí)任務(wù)的方法:

package com.rhwayfun.task;

import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @author ZhongCB
 * @date 2016年09月10日 14:30
 * @description
 */
@Component
public class App {

  public void execute1(){
    System.out.printf("Task: %s, Current time: %s\n", 1, LocalDateTime.now());
  }

  public void execute2(){
    System.out.printf("Task: %s, Current time: %s\n", 2, LocalDateTime.now());
  }

  public void execute3(){
    System.out.printf("Task: %s, Current time: %s\n", 3, LocalDateTime.now());
  }

  public void execute4(){
    System.out.printf("Task: %s, Current time: %s\n", 4, LocalDateTime.now());
  }

  public void execute5(){
    System.out.printf("Task: %s, Current time: %s\n", 5, LocalDateTime.now());
  }

  public void execute6(){
    System.out.printf("Task: %s, Current time: %s\n", 6, LocalDateTime.now());
  }

  public void execute7(){
    System.out.printf("Task: %s, Current time: %s\n", 7, LocalDateTime.now());
  }

  public void execute8(){
    System.out.printf("Task: %s, Current time: %s\n", 8, LocalDateTime.now());
  }

  public void execute9(){
    System.out.printf("Task: %s, Current time: %s\n", 9, LocalDateTime.now());
  }

  public void execute10(){
    System.out.printf("Task: %s, Current time: %s\n", 10, LocalDateTime.now());
  }

  public void execute11(){
    System.out.printf("Task: %s, Current time: %s\n", 11, LocalDateTime.now());
  }

}

spring配置文件如下:

?xml version="1.0" encoding="UTF-8"?>
beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
      http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd">

  !-- 配置注解掃描 -->
  context:component-scan base-package="com.rhwayfun.task"/>

  task:scheduler id="taskScheduler" pool-size="100" />

  task:scheduled-tasks scheduler="taskScheduler">
    !-- 每半分鐘觸發(fā)任務(wù) -->
    task:scheduled ref="app" method="execute1" cron="30 * * * * ?"/>
    !-- 每小時(shí)的10分30秒觸發(fā)任務(wù) -->
    task:scheduled ref="app" method="execute2" cron="30 10 * * * ?"/>
    !-- 每天1點(diǎn)10分30秒觸發(fā)任務(wù) -->
    task:scheduled ref="app" method="execute3" cron="30 10 1 * * ?"/>
    !-- 每月20號(hào)的1點(diǎn)10分30秒觸發(fā)任務(wù) -->
    task:scheduled ref="app" method="execute4" cron="30 10 1 20 * ?"/>
    !-- 每年10月20號(hào)的1點(diǎn)10分30秒觸發(fā)任務(wù) -->
    task:scheduled ref="app" method="execute5" cron="30 10 1 20 10 ?"/>
    !-- 每15秒、30秒、45秒時(shí)觸發(fā)任務(wù) -->
    task:scheduled ref="app" method="execute6" cron="15,30,45 * * * * ?"/>
    !-- 15秒到45秒每隔1秒觸發(fā)任務(wù) -->
    task:scheduled ref="app" method="execute7" cron="15-45 * * * * ?"/>
    !-- 每分鐘的每15秒時(shí)任務(wù)任務(wù),每隔5秒觸發(fā)一次 -->
    task:scheduled ref="app" method="execute8" cron="15/5 * * * * ?"/>
    !-- 每分鐘的15到30秒之間開始觸發(fā),每隔5秒觸發(fā)一次 -->
    task:scheduled ref="app" method="execute9" cron="15-30/5 * * * * ?"/>
    !-- 每小時(shí)的0分0秒開始觸發(fā),每隔3分鐘觸發(fā)一次 -->
    task:scheduled ref="app" method="execute10" cron="0 0/3 * * * ?"/>
    !-- 星期一到星期五的10點(diǎn)15分0秒觸發(fā)任務(wù) -->
    task:scheduled ref="app" method="execute11" cron="0 15 10 ? * MON-FRI"/>
  /task:scheduled-tasks>

/beans>

編寫測試代碼:

package com.rhwayfun.task;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author ZhongCB
 * @date 2016年09月10日 14:55
 * @description
 */
public class AppTest {

  public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/app-context-task.xml");
  }
}

運(yùn)行測試代碼,控制臺(tái)會(huì)定時(shí)輸出每個(gè)定時(shí)任務(wù)的日志信息,說明測試通過。

小插曲

由于項(xiàng)目使用jdk 1.8進(jìn)行開發(fā),所以初始的時(shí)候每次pom文件發(fā)生修改,編譯器的版本又變成了jdk 1.5,后面發(fā)現(xiàn)需要在pom文件中添加build便簽?zāi)遣糠植拍軐⒛J(rèn)的編譯器進(jìn)行修改。也算一個(gè)小收獲了。

如有疑問請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

您可能感興趣的文章:
  • Java之SpringBoot定時(shí)任務(wù)案例講解
  • Java下SpringBoot創(chuàng)建定時(shí)任務(wù)詳解
  • java Quartz定時(shí)器任務(wù)與Spring task定時(shí)的幾種實(shí)現(xiàn)方法
  • 最流行的java后臺(tái)框架spring quartz定時(shí)任務(wù)
  • Java spring定時(shí)任務(wù)詳解

標(biāo)簽:貸款邀約 廣州 樂山 黃石 內(nèi)江 南京 大連 銅川

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《java 中Spring task定時(shí)任務(wù)的深入理解》,本文關(guān)鍵詞  java,中,Spring,task,定時(shí),任務(wù),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《java 中Spring task定時(shí)任務(wù)的深入理解》相關(guān)的同類信息!
  • 本頁收集關(guān)于java 中Spring task定時(shí)任務(wù)的深入理解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章