java 定時器

昨天看定時器,被Quartz定時器框架困擾到現在,以爲是調用的時候出了問題,以爲是我不知道怎麼調用然後出的問題,結果是少了jar包。哎,這個問題真的是,告訴我們以後導入一個框架的jar包時,一定要導全,不要只導核心包,因爲核心包可能依賴其他包。

定時任務不執行原因:沒有導入除quartz-2.3.0-SHAPSHOT.jar以外的包。

解決方法,把其餘包都導入。

這個問題真的是!!!!!真是個值得記憶的教訓。現在來說說定時器吧!

我在理解定時器的時候,提出了這些問題!

首先,jdk自帶Timer,TimerTask類,可以實現定時任務,爲什麼還需要其他定時器框架呢?

用java自帶的類來做定時任務時,只需寫一個類,讓這個類extendsTimerTask,然後重寫它的Run()方法。

然後,如果把定時器放在監聽器裏的話,直接在監聽器的某個方法中執行Timer的schedule(task,...)方法。

我們可以發現,

schedule(task, 0, PERIOD*PERIODTIME);方法實現的定時種類不多。它不能控制一些複雜的定時任務。

所以這就是爲什麼要使用其他定時器框架的原因吧,因爲不能滿足複雜的任務需求。

那常見的定時器框架有哪些呢?

java定時器,Spring定時器,Quartz定時器。

我暫時只用過java自帶的定時器和Quartz定時器,因爲Quartz定時器已經夠強大了,我覺得了解Spring定時器也就沒必要了。

那Quartz定時器框架是怎麼用的呢?

首先我們要理解Quartz的幾個核心概念。

然後我們要引入我們需要的jar包,注意一個都不能少,不然會引發一系列問題,前面已經截圖過。

最後我們進入代碼部分。

我們要先建一個job類,它是任務的核心,即這個定時任務究竟要做什麼,就是做的內容。這個類需要implements該框架的Job類,然後實現它的execute()方法,方法的具體內容就是執行的這個任務,即任務的內容。

 然後,我們需要創建一個JobDetail。

JobDetail 表示一個具體的可執行的調度程序,Job 是這個可執行程調度程序所要執行的內容,另外 JobDetail 還包含了這個任務調度的方案和策略。最開始創建的job類就會在創建它時被用到。

接着呢,我們需要創建一個觸發器,Trigger

Trigger 代表一個調度參數的配置,什麼時候去調。它可以配置定時任務中的定時。尤其是cron表達式的配置,讓定時任務想怎麼定時就怎麼定時,配置可以在http://cron.qqe2.com/中生成,方便快捷。

最後呢,我們需要一個調度器,Scheduler。

Scheduler 代表一個調度容器,一個調度容器中可以註冊多個 JobDetail 和 Trigger。當 Trigger 與 JobDetail 組合,就可以被 Scheduler 容器調度了。剛剛創建的JobDetail和Trigger都需被它調度。

最後的最後,我們只需在監聽器或者其他地方直接調用剛剛寫好的方法即可,然後如果實在監聽器裏調用的話,程序一執行,定時任務就開始了。下面我粘一下我的代碼。

web.xml中的配置。

    <listener>
        <listener-class>com.practice.mylistener.QuartzListener</listener-class>
    </listener>

QuartzListener類。

package com.practice.mylistener;

import com.practice.tool.QuartzTimeManager;
import com.practice.tool.QuertzTask;
import com.practice.tool.job;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class QuartzListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("quertztask監聽器啓動==============================");
        QuartzTimeManager.addJob("myJob","group1","mytrigger","group1", job.class,"1-2 * * * * ?");
        System.out.println("task excute==================================");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

QuartzListener類

package com.practice.tool;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Collection;

public class QuartzTimeManager {
    private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

    /**
     * @Description: 添加一個定時任務
     *
     * @param jobName 任務名
     * @param jobGroupName  任務組名
     * @param triggerName 觸發器名
     * @param triggerGroupName 觸發器組名
     * @param jobClass  任務
     * @param cron   時間設置,參考quartz說明文檔
     */
    public static void addJob(String jobName, String jobGroupName,
                              String triggerName, String triggerGroupName, Class jobClass, String cron) {

        try {
            Scheduler sched = schedulerFactory.getScheduler();

            // 任務名,任務組,任務執行類
            JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();

            // 觸發器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();

            // 觸發器名,觸發器組
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();


            // 觸發器時間設定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));


            // 創建Trigger對象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();


            // 調度容器設置JobDetail和Trigger
            sched.scheduleJob(jobDetail, trigger);


            // 啓動
            if (!sched.isShutdown()) {
                System.out.println("=================定quartz定時任務開始");
                sched.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }



    /**
     * @Description: 修改一個任務的觸發時間
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName 觸發器名
     * @param triggerGroupName 觸發器組名
     * @param cron   時間設置,參考quartz說明文檔
     */
    public static void modifyJobTime(String jobName,
                                     String jobGroupName, String triggerName, String triggerGroupName, String cron) {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            if (trigger == null) {
                return;
            }


            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cron)) {
                /** 方式一 :調用 rescheduleJob 開始 */
                // 觸發器
                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                // 觸發器名,觸發器組
                triggerBuilder.withIdentity(triggerName, triggerGroupName);
                triggerBuilder.startNow();
                // 觸發器時間設定
                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                // 創建Trigger對象
                trigger = (CronTrigger) triggerBuilder.build();
                // 方式一 :修改一個任務的觸發時間
                sched.rescheduleJob(triggerKey, trigger);
                /** 方式一 :調用 rescheduleJob 結束 */


                /** 方式二:先刪除,然後在創建一個新的Job  */
                //JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                //Class<? extends Job> jobClass = jobDetail.getJobClass();
                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                /** 方式二 :先刪除,然後在創建一個新的Job */
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * @Description: 移除一個任務
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     */
    public static void removeJob(String jobName, String jobGroupName,
                                 String triggerName, String triggerGroupName) {
        try {
            Scheduler sched = schedulerFactory.getScheduler();


            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);


            sched.pauseTrigger(triggerKey);// 停止觸發器
            sched.unscheduleJob(triggerKey);// 移除觸發器
            sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 刪除任務
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * @Description:啓動所有定時任務
     */
    public static void startJobs() {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            sched.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * @Description:關閉所有定時任務
     */
    public static void shutdownJobs() {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            if (!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

job類

package com.practice.tool;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class job implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext)
            throws JobExecutionException {
        System.out.println("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
        Date date=new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Time:"+sf.format(date));
        System.out.println("Hello");
    }
}

運行結果:

最重要的一點,注意導入jar包要完整哦!其實定時器還是挺簡單的對不對。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章