JAVA-關於定時器,看這篇就夠了!

程序員可以讓步,卻不可以退縮,可以羞澀,卻不可以軟弱,總之,程序員必須是勇敢的。


一:序言

公司近期有一個項目需要用到定時功能,於是安排我調研一下java能用的定時器,要求如下:

  1. 配置簡單
  2. 方便啓停
  3. 運行準確可靠

二:調研過程

 

第一步—尋找定時器

這個過程大約花了我10分鐘這麼多,各大網站,關鍵詞一搜,出來一大堆,簡單一比較,目前市面上用的比較多的定時器主要有下面幾類:

序號 定時器 集成方式
1 Timer jdk自帶
2 Thread jdk自帶
3 Spring(@Scheduled) 需集成Spring/Spring Boot
4 quartz 需依賴quartz jar包

 

 

 

 

第二步—分析定時器

看代碼:

1.Timer

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        //do something
    }
    //delay爲首次執行run需等待的時間(ms)
    //period爲執行的週期(ms)
}, delay, period);

timer.cancel();//關閉定時器

 2.Thread

Thread thread = new Thread(new Runnable() {
      @Override
      public void run() {
          while (true) {
              // do something
          try {
              Thread.sleep(timeInterval);//每隔**ms run一次
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
          }
      }
   });
thread.start();                          

3.@Scheduled

(1)添加類的註解

@Component//把類注入Spring的上下文
@EnableScheduling//開啓定時任務

(2)定時器

關於cron的定義 百度一下就有很多

@Scheduled(cron = "0/1 * * * * * ?")
private void task(){
    //do something
}

4.quartz

(1)添加依賴 pom/jar/gradle

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

//gradle
implementation 'org.quartz-scheduler:quartz:2.4.0'

(2)添加配置

org.quartz.scheduler.instanceName = MyScheduler//調度名稱
org.quartz.threadPool.threadCount = 3 //線程數量
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore//RAM

(3)定時器

public class QuartzTest {

      public static void main(String[] args) {

          try {
              // Grab the Scheduler instance from the Factory
              Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

              // and start it off
              scheduler.start();

              scheduler.shutdown();

          } catch (SchedulerException se) {
              se.printStackTrace();
          }
      }
  }

 

爲了方便大家更好的進行選擇,在簡單的執行後,得出結論:

序號 定時器 集成難度 多線程難度 啓停難度 數據偏差 結論
1 Timer

無需集成

別用了,誤差大
2 Thread 無需集成 別用了,太麻煩
3 Spring(@Scheduled) 小(0-3ms) 輕量級Quartz
4 quartz 小(0-3ms) 框架重,配置複雜

 

 

 

 

第三步—選擇定時器

timer跟thread已經屬於比較落後的方法了,spring3.0以後自帶的scheduletask任務調度,不用配置就可以實現quartz的大部分功能,需要在定時器上有更深拓展的同學可以選擇Quartz,否則,選擇scheduletask吧!!!!

關於Quartz的使用詳解 大家可以看一下


"打入冷宮"的方法我們就不浪費時間進行贅述了,下面我將詳細描述單線程模式的ScheduleTask如何配置線程池進行有序的多調度,直接貼代碼


 

第四步—拓展定時器

1.目錄結構

2.yml文件

timer:
  #  每一秒執行一次
  corn1: 0/1 * * * * ?
  corn2: 0/1 * * * * ?

3.Controller文件

@RestController
public class TestController {

    @Autowired
    private TestConfig testConfig;

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    private ScheduledFuture<?> future1;

    private ScheduledFuture<?> future2;

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        return new ThreadPoolTaskScheduler();
    }

    @RequestMapping("/startCorn1")
    public String startCorn1() {
        future1 = threadPoolTaskScheduler.schedule(new MyRunnable(), new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                return new CronTrigger(testConfig.getCorn1()).nextExecutionTime(triggerContext);
            }
        });
        System.out.println("startCron1()");
        return "Start Corn1 Success";
    }

    @RequestMapping("/stopCron1")
    public String stopCron1() {
        if (future1 != null) {
            future1.cancel(true);
        }
        System.out.println("stopCron1()");
        return "Stop Corn1 Success";
    }

    @RequestMapping("/startCorn2")
    public String startCorn2() {
        future2 = threadPoolTaskScheduler.schedule(new MyRunnable2(), new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                return new CronTrigger(testConfig.getCorn2()).nextExecutionTime(triggerContext);
            }
        });
        System.out.println("startCron2");
        return "Start Cron2 Success";
    }

    @RequestMapping("/stopCron2")
    public String stopCron2() {
        if (future2 != null) {
            future2.cancel(true);
        }
        System.out.println("stopCron2()");
        return "Stop Corn2 Success";
    }


}

4.Runnable文件

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("MyRunnable1---->");
    }

}

5.config文件

@Component
@ConfigurationProperties(prefix = "timer")
public class TestConfig {
    private String corn1;
    private String corn2;

    public String getCorn1() {
        return corn1;
    }

    public void setCorn1(String corn1) {
        this.corn1 = corn1;
    }

    public String getCorn2() {
        return corn2;
    }

    public void setCorn2(String corn2) {
        this.corn2 = corn2;
    }
}

6.運行結果

(1)網頁運行結果

          

(2)打印臺顯示

           

 

三:結論

 

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