Java中定時的使用

一、定時

1、定時任務的適用場景

定時任務的場景可以說非常廣泛,比如某些視頻網站,購買會員後,每天會給會員送成長值,每月會給會員送一些電影券;比如在保證最終一致性的場景中,往往利用定時任務調度進行一些比對工作;比如一些定時需要生成的報表、郵件;比如一些需要定時清理數據的任務等。

2、定時任務實現的四種方式

JDK定時類、Quartz 框架、Spring註解定時和xml配置、SpringBoot定時任務。

二、JDK定時

Timer是一種定時器工具,用來在一個後臺線程計劃執行指定任務。它可以計劃執行一個任務一次或反覆多次。
  TimerTask一個抽象類,它的子類代表一個可以被Timer計劃的任務。具體的任務在TimerTask中run接口中實現。
  通過Timer中的schedule方法啓動定時任務。

1、在指定日期運行定時器任務,只運行一次

public static void main(String[] args) throws ParseException {
    String sdate = "2018-02-14";
    SimpleDateFormat sf = new SimpleDateFormat("yy-MM-dd");
    Date date = sf.parse(sdate);

    Timer timer = new Timer();
    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            System.out.println("系統正在運行……");
        }
    }, date); //在指定的日期運行一次定時任務
   /*如果date日期在今天之前,則啓動定時器後,立即運行一次定時任務run方法*/
   /*如果date日期在今天之後,則啓動定時器後,會在指定的將來日期運行一次任務run方法*/
}

2、在距當前時刻的一段時間後運行定時器任務,只運行一次

public static void main(String[] args) {
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            System.out.println("系統正在運行……");
        }
    }, 5000); //指定啓動定時器5s之後運行定時器任務run方法,並且只運行一次
}

3、在指定的時間後,每隔指定的時間,重複運行定時器任務

public static void main(String[] args) throws ParseException {
    String sdate = "2018-02-10";
    SimpleDateFormat sf = new SimpleDateFormat("yy-MM-dd");
    Date date = sf.parse(sdate);

    Timer timer = new Timer();
    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            System.out.println("系統正在運行……");
        }
    }, date, 2000);
    /*如果指定的date時間是當天或者今天之前,啓動定時器後會立即每隔2s運行一次定時器任務*/
    /*如果指定的date時間是未來的某天,啓動定時器後會在未來的那天開始,每隔2s執行一次定時器任務*/
}

4、在距當前時刻的一段指定距離後,每隔指定時間運行一次定時器任務

public static void main(String[] args) {
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            System.out.println("系統正在運行……");
        }
    }, 5000, 2000);
    /*當啓動定時器後,5s之後開始每隔2s執行一次定時器任務*/
}

停止定時器的四種方式

1、調用Timer的cancel方法;
  2、把Timer線程設置成Daemon守護線程,當所有的用戶線程結束後,那麼守護線程也會被終止;
  3、當所有的任務執行結束後,刪除對應Timer對象的引用,線程也會被終止;
  4、調用System.exit方法終止程序

三、Quartz

Quartz是一個完全由Java編寫的開源作業調度框架,爲在Java應用程序中進行作業調度提供了簡單卻強大的機制。

1、pom文件

  <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.0</version>
    </dependency>

2、實現job接口在execute方法寫相關業務

public class TestJob implements Job {

    private Logger logger = LoggerFactory.getLogger(TestJob.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
         System.out.println("業務寫在這裏");
         logger.info(Thread.currentThread().getName() + " test job begin " + new Date());
    }
}

3、測試類

public static void main(String[] args) throws InterruptedException, SchedulerException {

    Scheduler scheduler = new StdSchedulerFactory().getScheduler();
    // 開始
    scheduler.start();
    // job 唯一標識 test.test-1
    JobKey jobKey = new JobKey("test" , "test-1");
    JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
    Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("test" , "test")
            // 延遲一秒執行
            .startAt(new Date(System.currentTimeMillis() + 1000))
            // 每隔一秒執行 並一直重複
            .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
            .build();
    scheduler.scheduleJob(jobDetail , trigger);
    Thread.sleep(5000);
    // 刪除job
    scheduler.deleteJob(jobKey);
}
public static void main(String[] args) throws InterruptedException, SchedulerException {

    Scheduler scheduler = new StdSchedulerFactory().getScheduler();
    // 開始
    scheduler.start();
    // job 唯一標識 test.test-1
    JobKey jobKey = new JobKey("test" , "test-1");
    JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
    // 可以設置定時任務具體時間
    CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("test", "test-1").withSchedule(
            CronScheduleBuilder.cronSchedule("/2 * * * * ?")
    ).build();
    scheduler.scheduleJob(jobDetail , trigger);
    Thread.sleep(5000);
    // 刪除job
    scheduler.deleteJob(jobKey);
}

四、Spring定時

1、註解版本

<task:annotation-driven />
配置掃描任務位置
<!-- 掃描任務 -->
<context:component-scan base-package="com.vrveis.roundTrip.task" />

package com.vrveis.roundTrip.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class FlightTrainTask {

    @Scheduled(cron = "0/5 * * * * ? ") // 間隔5秒執行
    public void taskCycle() {
        System.out.println("使用Spring框架配置定時任務");
    }
}

2、Xml版本

<context:component-scan base-package="com" />
<!-- spring框架的Scheduled定時器 -->
<task:scheduled-tasks>
    <task:scheduled ref="springTiming" method="test" cron="0 0 12 * * ?"/>
</task:scheduled-tasks>


public class SpringTiming {

      public void test(){ 
           System.out.println("使用Spring定時任務");
      }
}

五、SpringBoot實現定時

1、pom文件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

2、啓動類添加@EnableScheduling 註解

 @SpringBootApplication
 @EnableScheduling
 public class Application {

         public static void main(String[] args) {
               SpringApplication.run(Application.class, args);
         }
}

3、創建定時任務類

@Component
public class SchedulerTask {


       private Logger logger = LoggerFactory.getLogger(SchedulerTask.class);

       private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

       private int count = 0;

       @Scheduled(cron="*/6 * * * * ?")
       private void process(){
              logger.info("this is scheduler task runing  "+(count++));
       }

       @Scheduled(fixedRate = 6000)
       public void reportCurrentTime() {
              logger.info("現在時間:" + dateFormat.format(new Date()));
       }
}

4、運行結果

2019-01-19 14:49:12.025  INFO 17024 --- [pool-1-thread-1] 
c.example.springbootdemo.SchedulerTask   : this is scheduler task runing  0
2019-01-19 14:49:13.109  INFO 17024 --- [pool-1-thread-1] 
c.example.springbootdemo.SchedulerTask   : 現在時間:14:49:13

通過運行結果看到是一個線程執行定時任務,如果在同一時間啓動多個定時器怎麼辦?

增加一個配置類

@Configuration
//所有的定時任務都放在一個線程池中,定時任務啓動時使用不同都線程。
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
       //設定一個長度10的定時任務線程池
       taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
    }
}

測試結果可以看出現在是多個線程運行定時器。

 2019-01-19 14:51:30.025  INFO 18392 --- [pool-1-thread-2] 
 c.example.springbootdemo.SchedulerTask   : this is scheduler task runing  0
 2019-01-19 14:51:32.214  INFO 18392 --- [pool-1-thread-1] 
 c.example.springbootdemo.SchedulerTask   : 現在時間:14:51:32

Cron表達式

在這裏插入圖片描述

corn從左到右(用空格隔開):秒 分 小時 月份中的日期 月份 星期中的日期 年份

Cron表達式生成器
  http://cron.qqe2.com/

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