1. 程式人生 > 其它 >java定時器

java定時器

一、@Scheduled註解

這是基於註解可實現定時任務。

實現:

1、

@EnableScheduling註解到定時方法的類上,或者直接註解到啟動類。

2、

@Scheduled註解到定時方法上
@Scheduled有以下引數:
1     @Scheduled(fixedDelay = 3000) //方法執行完成後等待3秒再次執行
2     @Scheduled(fixedRate = 3000)  //方法每隔3秒執行一次
3     @Scheduled(initialDelay = 2000,fixedRate = 4000) //延遲2秒執行第一次,之後每隔4秒執行一次
4     @Scheduled(fixedDelayString ="${time.demo}") //
可以執行配置檔案中的,方法執行完成後等待time.demo再次執行 5 @Scheduled(fixedRateString ="${time.demo}" ) //可以執行配置檔案中的,法每隔time.demo執行一次 6 @Scheduled(cron = "0 0,30 0,8 ? * ? ") //cron表示式,方法在每天的8點30分0秒執行,引數為字串型別

cron表示式,推薦看這篇文章:https://www.jianshu.com/p/1defb0f22ed1

示例:

每隔3秒執行一次。

1 @Component
2 @EnableScheduling
3 public class testScheduled {
4 5 @Scheduled(fixedRate = 3000) 6 public void call(){ 7 System.out.println("每隔3秒列印一次"); 8 } 9 }

優點:簡單,只需要兩個註解即可

缺點:引數和方法都必須寫到程式碼裡面

 

二、Timer().schedule建立任務

直接上示例,2秒後執行第一次,然後每隔4秒執行一次。

 1 @Component
 2 public class testTimer {
 3     {
 4         doTimer();
 5     }
 6     public
void doTimer(){ 7 //建立timer物件 8 Timer timer = new Timer(); 9 //建立TimerTask物件 10 TimerTask timerTask = new TimerTask() { 11 //重寫run方法,就是具體定時做什麼事情 12 @Override 13 public void run() { 14 System.out.println(new Date().toString()); 15 } 16 }; 17 //timer來執行timerTask 18 timer.schedule(timerTask,2000,4000); 19 } 20 }

幾個概念:

Timer:即定時器,為java自帶的工具類,提供定時執行任務的相關功能

timer有3個核心方法:

1、新增任務(6種)

schedule(TimerTask task, long delay):指定任務task,在delay毫秒延遲後執行
schedule(TimerTask task, Date time):指定任務task,在time時間點執行一次
schedule(TimerTask task, long delay, long period):指定任務task,延遲delay毫秒後執行第一次,並在之後每隔period毫秒執行一次
schedule(TimerTask task, Date firstTime, long period):指定任務task,在firstTime的時候執行第一次,之後每隔period毫秒執行一次
scheduleAtFixedRate(TimerTask task, long delay, long period):作用與schedule一致
scheduleAtFixedRate(TimerTask task, Date firstTime, long period):作用與schedule一致
實際上最後都會使用sched(TimerTask task, long time, long period),即指定任務task,在time執行第一次,之後每隔period毫秒執行一次

schedule使用系統時間計算下一次,即System.currentTimeMillis()+period

而scheduleAtFixedRate使用本次預計時間計算下一次,即time + period

對於耗時任務,兩者區別較大,請按需求選擇,瞬時任務無區別。

2、取消任務方法:cancel(),會將任務佇列清空,並堵塞執行緒,且不再能夠接受任務(接受時報錯),並不會銷燬本身的例項和其內部的執行緒。

3、淨化方法:purge(),淨化會將佇列裡所有被取消的任務移除,對剩餘任務進行堆排序,並返回移除任務的數量。

TimerTask:實際上就是一個Runnable而已,繼承Runnable並添加了幾個自定義的引數和方法,說白了就是在這裡面寫定時的具體方法。

TaskQueue:即任務佇列,Timer生產任務,然後推到TaskQueue裡存放,等待處理,被處理掉的任務即被移除掉。

注:TaskQueue實質上只有一個長度為128的陣列用於儲存TimerTask、一個int型變數size表示佇列長度、以及對這兩個資料的增刪改查。

TimerThread:即定時器執行緒,執行緒會共享TaskQueue裡面的資料,TimerThread會對TaskQueue裡的任務進行消耗。

注:TimerThread實際上就是一個Thread執行緒,會不停的監聽TaskQueue,如果佇列裡面有任務,那麼就執行第一個,並將其刪除(先刪除再執行)。

三、執行緒

1、通過執行緒的sleep來造成延時的效果

示例1:thread + runnable

 1 @Component
 2 public class testThreadAndRunnable {
 3     
 4     private Integer count = 0;
 5     
 6     public testThreadAndRunnable() {
 7         test1();
 8     }
 9     public void test1() {
10         new Thread(() -> {
11             while (count < 10) {
12                 System.out.println(new Date().toString() + ": " + count);
13                 count++;
14                 try {
15                     Thread.sleep(3000);
16                 } catch (InterruptedException e) {
17                     e.printStackTrace();
18                 }
19             }
20         }).start();
21     }
22 }

示例2:執行緒池 + runnable

 1 @Component
 2 public class testThreadPool {
 3     private static final ExecutorService threadPool = Executors.newFixedThreadPool(5);// 執行緒池
 4     private Integer count = 0;
 5     public testThreadPool() {
 6         test2();
 7     }
 8     public void test2() {
 9         threadPool.execute(() -> {
10             while (count < 10) {
11                 System.out.println(new Date().toString() + ": " + count);
12                 count++;
13                 try {
14                     Thread.sleep(3000);
15                 } catch (InterruptedException e) {
16                     e.printStackTrace();
17                 }
18             }
19         });
20     }
21 }

 

2、使用ScheduledTask + runnable

示例:
@Component
public class testScheduledTask {
    private Integer count = 0;
    @Autowired
    private TaskScheduler taskScheduler;
    public testScheduledTask(TaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
        test4();
        test5();
        test6();
    }
    //設定間隔時間,每2秒執行一次
    public void test4() {
        taskScheduler.scheduleAtFixedRate(() -> {
            System.out.println(new Date().toString() + ": " + count+"設定間隔時間2秒");
            count++;
        }, 2000);
    }
    //可以用Cron表示式,每天凌晨1點執行
    public void test5() {
        taskScheduler.schedule(() -> {
            System.out.println(new Date().toString() + ": " + count+"凌晨1點執行");
            count++;
        }, new CronTrigger("0 0 1 * * ?"));
    }
    //設定間隔時間,每5.5秒執行一次
    public void test6() {
        taskScheduler.scheduleAtFixedRate(() -> {
            System.out.println(new Date().toString() + ": " + count+"設定間隔時間5.5秒");
            count++;
        }, 5500);
    }
}

 



參考部落格:(118條訊息) 【JAVA定時器】四種常見定時器的原理和簡單實現_Echo-YeZi的部落格-CSDN部落格_java 定時器