1. 程式人生 > >史上最全最詳細的Spring定時任務的講解以及例項

史上最全最詳細的Spring定時任務的講解以及例項

一、最原始的定時任務

1.採用執行緒方式

public static void runTask(){
        final long timeInterval = 1000;
        Runnable runnable = new Runnable() {
            public void run() {
                while (true){
                    System.out.println("hello");
                    try {
                        Thread.sleep(timeInterval);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }

二、採用jdk中的Timer類
package com.flx.timer;

import com.flx.timer.task.SimpleTask;
import com.flx.timer.task.SimpleTaskLiving;
import com.flx.util.BaseFunction;
import com.flx.util.date.CalendarUtils;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by Fenglixiong on 2017/9/25.
 */
public class TimerHome {

    private static Timer timer = new Timer();

    public static void main(String[] args) {

        TaskOne(10);
        TaskTwo(CalendarUtils.addSeconds(new Date(),10));
        TaskThree(CalendarUtils.addSeconds(new Date(),10));
        TaskFour();
        TaskFive(CalendarUtils.addSeconds(new Date(),10));
        TaskSix();
        TimerTaskPool();
        TimerTask01();
        TimerTask02();
    }

    /**
     * 指定延遲時間執行定時任務
     * @param time
     */
    public static void TaskOne(int time){
        BaseFunction.console("準備執行任務TaskOne...");
        Timer timer = new Timer();
        timer.schedule(new SimpleTask(),time*1000);
    }

    /**
     * 在指定時間執行任務
     * @param date
     */
    public static void TaskTwo(Date date){
        BaseFunction.console("準備執行任務TaskTwo...");
        CalendarUtils.sayTime(new Date());
        Timer timer = new Timer();
        timer.schedule(new SimpleTask(),date);
    }

    /**
     * 在指定時間執行然後以指定時間間隔執行任務
     * @param date
     */
    public static void TaskThree(Date date){
        BaseFunction.console("準備執行任務TaskThree...");
        CalendarUtils.sayTime(new Date());
        Timer timer = new Timer();
        timer.schedule(new SimpleTaskLiving("TaskThree"),date,3000);
    }

    /**
     * 在指定時間延遲之後執行然後以指定時間間隔執行任務
     *
     */
    public static void TaskFour(){
        BaseFunction.console("準備執行任務TaskFour...");
        CalendarUtils.sayTime(new Date());
        Timer timer = new Timer();
        timer.schedule(new SimpleTaskLiving("TaskFour"),5000,3000);
    }

    /**
     * 在指定時間延遲之後執行然後以指定時間間隔執行任務
     *
     */
    public static void TaskFive(Date firstTime){
        BaseFunction.console("準備執行任務TaskFive...");
        CalendarUtils.sayTime(new Date());
        Timer timer = new Timer("TaskFive");
        timer.scheduleAtFixedRate(new SimpleTaskLiving(),firstTime,3000);
    }

    /**
     * 在指定時間延遲之後執行然後以指定時間間隔執行任務
     *
     */
    public static void TaskSix(){
        BaseFunction.console("準備執行任務TaskSix...");
        CalendarUtils.sayTime(new Date());
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new SimpleTaskLiving("TaskSix"),20000,3000);
    }

    /**
     * TimerTask01();
     * TimerTask02();
     * 同時執行這兩個task
     * 1.如果是兩個Timer的話相當於兩個執行緒互相不會影響
     * 2.如果是一個Timer的話計劃執行兩個定時任務的話
     *      其中一個延遲或者阻塞會影響另一個任務的執行
     */
    public static void TimerTask01(){
        CalendarUtils.sayTime(new Date());
        timer.schedule(new TimerTask() {
            public void run() {
                System.out.println("start:TimerTask01");
                try {
                    BaseFunction.console("執行:--->TimerTask01");
                    Thread.sleep(15000);    //執行緒休眠3000
                    BaseFunction.console("休眠後--->TimerTask01");
                    CalendarUtils.sayTime(new Date());
//                    throw new RuntimeException();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 1000);
    }

    public static void TimerTask02(){
        CalendarUtils.sayTime(new Date());
        timer.schedule(new TimerTask() {
            public void run() {
                System.out.println("執行:TimerTask02");
                CalendarUtils.sayTime(new Date());
//                throw new RuntimeException("...");
            }
        }, 5000);
    }

    /**
     * ScheduledExecutorService是從Java SE5的java.util.concurrent裡,
     * 做為併發工具類被引進的,這是最理想的定時任務實現方式。
     */
    public static void TimerTaskPool(){

        Runnable runnable = new Runnable() {
            public void run() {
                // task to run goes here
                System.out.println("Hello !!");
            }
        };

        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(runnable,10,1, TimeUnit.SECONDS);

    }

}

/**
 schedule(TimerTask task, Date time):安排在指定的時間執行指定的任務。
 schedule(TimerTask task, Date firstTime, long period) :安排指定的任務在指定的時間開始進行重複的固定延遲執行。
 schedule(TimerTask task, long delay) :安排在指定延遲後執行指定的任務。
 schedule(TimerTask task, long delay, long period) :安排指定的任務從指定的延遲後開始進行重複的固定延遲執行。
 同時也過載了scheduleAtFixedRate方法,scheduleAtFixedRate方法與schedule相同,只不過他們的側重點不同,區別後面分析。
 scheduleAtFixedRate(TimerTask task, Date firstTime, long period):安排指定的任務在指定的時間開始進行重複的固定速率執行。
 scheduleAtFixedRate(TimerTask task, long delay, long period):安排指定的任務在指定的延遲後開始進行重複的固定速率執行。
 */

/**
 * TimerTask

 TimerTask類是一個抽象類,由Timer 安排為一次執行或重複執行的任務。它有一個抽象方法run()方法,
 該方法用於執行相應計時器任務要執行的操作。因此每一個具體的任務類都必須繼承TimerTask,然後重寫run()方法。
 另外它還有兩個非抽象的方法:
 boolean cancel():取消此計時器任務。
 long scheduledExecutionTime():返回此任務最近實際執行的安排執行時間。
 */

三、Spring自身整合的Task任務

(1)配置檔案方式

<?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:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">

    <!--此任務寫到註解執行了-->
    <!--<task:scheduled-tasks>-->
        <!--<task:scheduled ref="simpleTaskJob" method="jobOne" cron="0/2 * * * * ?"/>-->
    <!--</task:scheduled-tasks>-->
    
    <!--新聞抓取-->
    <task:scheduled-tasks>
        <task:scheduled ref="simpleTaskService" method="sayHello" cron="0/2 * * * * ?" fixed-delay="1000"/>
    </task:scheduled-tasks>

    <!--債券抓取-->
    <task:scheduled-tasks>
        <task:scheduled ref="simpleTaskService" method="sayGood" cron="0/5 * * * * ?" />
    </task:scheduled-tasks>

    <!--上證E互動-->
    <task:scheduled-tasks>
        <task:scheduled ref="simpleTaskService" method="sayLove" cron="0/10 * * * * ?" />
    </task:scheduled-tasks>

    <!--公告-->
    <task:scheduled-tasks>
        <task:scheduled ref="simpleTaskService" method="sayNo" cron="0/15 * * * * ?" />
    </task:scheduled-tasks>

    <!--港交所股票持有數抓取-->
    <task:scheduled-tasks>
        <task:scheduled ref="simpleTaskService" method="sayYes" cron="0/20 * * * * ?" />
    </task:scheduled-tasks>

</beans>

<!--

欄位   允許值   允許的特殊字元
秒    0-59    , - * /
分    0-59    , - * /
小時    0-23    , - * /
日期    1-31    , - * ? / L W C
月份    1-12 或者 JAN-DEC    , - * /
星期    1-7 或者 SUN-SAT    , - * ? / L C #
年(可選)    留空, 1970-2099    , - * /
- 區間
* 萬用字元
? 你不想設定那個欄位
下面只例出幾個式子

CRON表示式    含義
"0 0 12 * * ?"    每天中午十二點觸發
"0 15 10 ? * *"    每天早上10:15觸發
"0 15 10 * * ?"    每天早上10:15觸發
"0 15 10 * * ? *"    每天早上10:15觸發
"0 15 10 * * ? 2005"    2005年的每天早上10:15觸發
"0 * 14 * * ?"    每天從下午2點開始到2點59分每分鐘一次觸發
"0 0/5 14 * * ?"    每天從下午2點開始到2:55分結束每5分鐘一次觸發
"0 0/5 14,18 * * ?"    每天的下午2點至2:55和6點至6點55分兩個時間段內每5分鐘一次觸發
"0 0-5 14 * * ?"    每天14:00至14:05每分鐘一次觸發
"0 10,44 14 ? 3 WED"    三月的每週三的14:10和14:44觸發
"0 15 10 ? * MON-FRI"    每個週一、週二、週三、週四、週五的10:15觸發

-->
(2)註解方式

首先要開啟註解驅動

<task:annotation-driven scheduler="poolScheduler" mode="proxy"/>
<task:scheduler id="poolScheduler" pool-size="10"/>

任務類

@Service
public class SimpleTaskJob {

    private int count = 0;

    /**
     * ApplicationContext.xml中配置了註解驅動之後完美執行任務
     * 下面解除註釋就可以執行
     */
    @Scheduled(cron = "0/2 * * * * ?")
    public void jobOne() {
        System.out.println("jobOne任務中....."+(++count));
    }

}
四、Spring結合Quartz實現精確定時任務

(1)最標準的寫法

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

    <!--1.增加執行緒池,用於任務註冊-->
    <bean id="poolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="10"/>
        <property name="maxPoolSize" value="20"/>
        <property name="queueCapacity" value="500"/>
    </bean>

    <!--2.定義業務邏輯處理類-->
    <bean id="simpleTask" class="com.flx.quartz.schedule.SimpleTask"/>

    <!--3.增加排程業務邏輯-->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="simpleTask"/>
        <property name="targetMethod" value="doTask"/>
    </bean>

    <!--4.增加排程觸發器-->
    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail"/>
        <property name="startDelay" value="3000"/>
        <property name="repeatInterval" value="2000"/>
    </bean>
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail"/>
        <property name="cronExpression" value="0/3 * * * * ?"/>
    </bean>

    <!--5.增加排程-->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="simpleTrigger"/>
                <ref bean="cronTrigger"/>
            </list>
        </property>
        <property name="taskExecutor" ref="poolTaskExecutor"/>
    </bean>
</beans>

(2)複雜的Quartz呼叫
<?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:mvc="http://www.springframework.org/schema/mvc" 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.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">

    <!--定時器資料,可選-->
    <bean id="message" class="com.flx.app.entity.Message">
        <property name="status" value="100"/>
        <property name="message" value="very good"/>
    </bean>

    <bean id="methodTask" class="com.flx.quartz.schedule.MethodTask"/>

<!--Job任務類start-->
    <!-- For times when you just need to invoke a method on a specific object -->
    <bean id="simpleTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="methodTask"/>
        <property name="targetMethod" value="sayHello"/>
    </bean>

    <bean id="firstComplexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.flx.quartz.schedule.FirstComplexJobDetail"/>
        <property name="jobDataMap">
            <map>
                <entry key="message" value-ref="message"/>
            </map>
        </property>
        <!--即使trigger不關聯也不會被刪除-->
        <property name="durability" value="true"/>
    </bean>

    <bean id="secondComplexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.flx.quartz.schedule.SecondComplexJobDetail"/>
        <property name="durability" value="true"/>
    </bean>


    <!--如果你需要更高階的設定,需要給作業傳遞資料,想更加靈活的話就使用這種方式。-->
    <bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.flx.quartz.schedule.SimpleQuartzJob"/>
        <property name="jobDataMap">
            <map>
                <entry key="message" value-ref="message"/>
            </map>
        </property>
        <!--如果一個任務不是durable,那麼當沒有Trigger關聯它的時候,它就會被自動刪除。-->
        <property name="durability" value="true"/>
        <property name="description" value="簡單的作業實現"/>
    </bean>
<!--Job任務類end-->

<!--A簡單觸發器-->
    <!--配置 Quartz 排程時要使用到的觸發器-->
    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="simpleTask"/>
        <property name="startDelay" value="3000"/>
        <property name="repeatInterval" value="2000"/>
        <property name="repeatCount" value="4"/>
        <!--<property name="startTime" value=""/>-->
    </bean>
<!--B計劃觸發器-->
    <!--這種型別更加靈活,允許你針對特定例項選擇計劃方案以及將來要執行的頻率。-->
    <bean id="firstCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="firstComplexJobDetail"/>
        <property name="cronExpression" value="0/5 * * ? * *"/>
    </bean>
    <bean id="secondCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="secondComplexJobDetail"/>
        <property name="cronExpression" value="0/10 * * ? * *"/>
    </bean>


<!--將任務和計劃全部整合在以前-->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="simpleTrigger"/>
                <ref bean="firstCronTrigger"/>
                <ref bean="secondCronTrigger"/>
            </list>
        </property>
    </bean>

</beans>

最後開啟測試類

public static void main(String[] args) {
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("timer/spring-quartz-task.xml");
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("timer/simple-quartz-task.xml");
    }





相關推薦

詳細Spring定時任務講解以及例項

一、最原始的定時任務 1.採用執行緒方式 public static void runTask(){ final long timeInterval = 1000; Runnable runnable = new Runnable() {

強SpringMVC詳細示例實戰教程

tin turn 方法 流程圖 瀏覽器 學習 this b- converter SpringMVC學習筆記---- 一、SpringMVC基礎入門,創建一個HelloWorld程序 1.首先,導入SpringMVC需要的jar包。 2.添加Web.xm

詳細JNDI數據源配置說明

獲取 eba top memory -h lse b2c gin stand 史上最全最詳細JNDI數據源配置說明 轉載 : https://blog.csdn.net/zhanglf02/article/details/76726702 2017年08月05日 17

69 道 Spring 面試題和答案

str 路徑 輕量 情況下 list 開發 erp throw 解決方案 史上最全 69 道 Spring 面試題和答案 目錄Spring 概述依賴註入Spring beansSpring註解Spring數據訪問Spring面向切面編程(AOP)Spring MVC S

詳細JNDI資料來源配置說明

環境:tomcat6.0+Maven 要使用資料來源就要知道資料來源的由來:在java開發使用jdbc都要經歷這四步 ①載入資料庫驅動程式:(Class.forName(“資料庫驅動類”);) ②連線資料庫(Connection con = DriverMan

69道Spring面試題和答案

目錄 Spring 概述 依賴注入 Spring beans Spring註解 Spring資料訪問 Spring面向切面程式設計(AOP) Spring MVC Spring 概述 1. 什麼是spring? Spring 是個java企業級應用的開源開發

詳細——Mac安裝MySQL步驟(內含E325報錯,command not found等問題)

MySQL Mac 安裝步驟 Mac 電腦就是指蘋果電腦,很多人安裝MySQL不夠順利(小編安了好久,深知安裝不易,特寫此文)。所以提供一個Mac版本的MySQL資料庫的安裝步驟。 MySQL是資料庫伺服器軟體,相對於應用軟體來說安裝步驟比較繁瑣,包含如下步驟: 1. 下載MySQL資源

的java spring註解,沒有之一

註解是個好東西,但好東西我們也是看見過,整理過,理解過,用過才知道好。不求我們每個都記住,但求保有印象,在需要的時候能提取出來再查詢相關資料,平時工作就不會顯得那麼被動了。[email protected]註解該類等價 與XML中配置beans,相當於Ioc容器,它

SpringMVC 詳細示例實戰教程

Spring MVC 入門教程二: 一個簡單的入門例項教程 該例項的原始碼和例項中的jar 簡單註解配置的例項: 一、建立專案: 1、建立新的動態web專案: 2、為專案命名為:SpringMVC

JAVA面試-- 69 道 Spring 面試題和答案

開發十年,就只剩下這套架構體系了! >>>   

詳細的IO流教程,沒有之一!

目錄 1、告白IO流的四點明確 2、File類 1.1 File概述 1.2 構造方法 1.3 常用方法 1.3.1 獲取功能的方法 1.3.2 絕對路徑和相對

正確的zabbix server安裝過程

zabbix安裝 zabbix server 說在前面的話:本例使用的是centos7、zabbix2.2.6版本,其他版本需要再驗證不要使用yum安裝tomcat和jdk,否則安裝zabbix會報錯正文:一、Lamp安裝及準備工作yum -y install httpd mysql mysql-se

自動化測試 - Appium + Python簡環境搭建步驟

一,為什麼是Appium借一張圖:   1.1 Appium優點 l  開源 l  跨架構:NativeApp、Hybird App、Web App l  跨裝置:Android、iOS、Firefox OS l  不依賴原始碼 l 

權威的Android Studio外掛整理

現在Android的開發者基本上都使用Android Studio進行開發(如果你還在使用eclipse那也行,畢竟你樂意怎麼樣都行)。使用好Android Studio外掛能大量的減少我們的工作量。 1.GsonFormat 快速將json字串轉換成一個Java Bea

後端---小白簡單細緻的Java接入微信支付介面(Native接入)

距離上一篇部落格 史上最全最小白最簡單最細緻的Java接入支付寶支付介面方法   https://blog.csdn.net/weixin_42504145/article/details/85077635 已經過去快三天了,終於在今天將微信整個電腦網頁支付整合在SSM框

後端---小白簡單細緻的Java接入支付寶支付介面方法

昨天Boss在講專案的業務需求的時候對我突然說讓我做一下支付寶微信支付介面這塊功能,我的心裡是充滿問號的????,但是我的嘴卻堅定的說出了沒問題!!!                     &n

嚴選 | Elasticsearch常用工具清單【轉】

1、題記 工欲善其事必先利其器,ELK Stack的學習和實戰更是如此,特將工作中用到的“高效”工具分享給大家。 希望能借助“工具”提高開發、運維效率! 2、工具分類概覽 2.1 基礎類工具 1、Head外掛 1)功能概述: ES叢集狀態檢視、索引資料檢視、ES DSL實現(增、刪、改、查操作)比較實用的地方

前端面試知識點(附答案)

一.html & js & css 1.AMD和CMD是什麼?它們的區別有哪些? AMD和CMD是二種模組定義規範。現在都使用模組化程式設計,AMD,非同步模組定義;CMD,通用模組定義。AMD依賴前置,CMD依賴就近。CMD的API職責單一,沒有全域性

強大的VIM學習資料

Vim 是 Linux 系統上的最著名的文字/程式碼編輯器,也是早年的 Vi 編輯器的加強版,而 gVim 則是其 Windows 版。它的最大特色是完全使用鍵盤命令進行編輯,脫離了滑鼠操作雖然使得入門變得困難,但上手之後鍵盤流的各種巧妙組合操作卻能帶來極為大幅的效率提

強大VIM操作

簡評:Vim編輯器在程式設計師界可謂無人不知,無人不曉,它功能強大,擴充套件性極高。小編就經常看到高手可以使用Vim熟練地對文字進行各種操作,那可以比滑鼠點來點去快得多了。但想成為Vim高手可沒那麼簡單,擺在我們這些新手的第一關就是記憶Vim下各種快捷鍵的用法,為了方便大