Java 中的定時任務(一)
定時任務簡單來說就是在指定時間,指定的頻率來執行一個方法,而在 Java 中我們又該如何實現呢?
想來主要有 3 種方式,最原始的方式肯定是開啟一個執行緒,讓它睡一會跑一次睡一會跑一次這也就達到了定頻率的執行 run 方法,我們只需要將業務邏輯寫在 run 方法中即可。這種方式總結就是單個執行緒來執行單個任務。
方式一:建立一個執行緒
package com.yu.task;import java.util.Date;public class ThreadTest { public static void main(String[] args) { // 設定執行週期 final long timeInterval = 3000; Runnable runnable = new Runnable() { public void run() { while (true) { System.out.println("Task Run ... " + new Date()); try { Thread.sleep(timeInterval); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread thread = new Thread(runnable); thread.start(); } }
第二種方式:使用 JDK 自帶的 API Timer 以及 TaskTimer。
這種方式和第一種簡單粗暴的方式有什麼區別呢,主要體現在使用 API 可以在指定的時間開始啟動任務,可以延期執行首次任務,同樣也看可以設定一定的時間間隔,但是原理是是一樣的,後臺還是啟動了一個執行緒,應該說是隻有一個執行緒在執行任務,不管我們啟動的 Task 有幾個。所以這也會有問題,比方說一個一個任務沒有執行完成,另一個任務就開始執行了,可能會發生併發問題。還有若是一個任務中報錯,則執行緒就會被停止。
package com.yu.task;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class MyTask extends TimerTask{ private String name; public MyTask(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void run() { SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String format = sf.format(new Date()); System.out.println("exec MyTask ... 當前時間為:" + format); System.out.println(this.name +" 正在執行!" + sf.format(new Date())); } public static void main(String[] args) { Timer timer = new Timer(); TimerTask task1 = new MyTask("Tasks 1"); TimerTask task2 = new MyTask("Tasks 2"); Calendar calendar1 = Calendar.getInstance(); calendar1.add(Calendar.SECOND, 3); Calendar calendar2 = Calendar.getInstance(); calendar2.add(Calendar.SECOND, 5); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String format = sf.format(new Date()); System.out.println("當前時間為:" + format); timer.schedule(task1, calendar1.getTime(), 3000L); timer.schedule(task2, calendar2.getTime(), 3000L); } }
其實在 Timer 中,封裝了一個 Task 的佇列和 Time 的執行緒物件,我們自定義的 Task 的引用會放在佇列中等待執行。
大致是這麼一個關係 Timer - TimerThread - TaskQueue - MyTask - run 當然最終執行的方法肯定是我們自定義任務中的 run 方法。因為我們自定義的任務已經繼承了 TimeTask ,而這個類已經實現了 Runnable 介面。
Timer 定時器第一種方式好的地方還在於可以選擇關閉任務,檢視任務的執行情況等。下面介紹幾個相關的方法。
啟動定時任務也有幾個不同的方法,每個都有不同的使用場景。
上面是 Timer 類中的屬性和方法的簡圖,開啟一個任務我們主要使用 6 個方法, 一共 3 組,先看簡單的
schedule() 方法中含有兩個引數,主要是用來執行一次任務的,不存在頻率的問題,而 3 個參數列示執行什麼任務,什麼時候開始執行/延時多久執行,多久執行一次。
現在來假設一個場景,01秒開始執行一個任務,頻率是 3 秒執行一次,不知道你們有沒有想到這個情況,若是這個方法本身執行需要 4 秒,那第二次執行的時間是 04 呢? 還是 05 秒呢?
而這個差別就是 schedule 和 scheduleAtFixedRate 方法的區別,前者會按照任務執行的情況來執行下一次任務,也就是說 01 之後,會等第一次執行結束再開始第二次,這樣就會帶來一個問題,每次執行時間都比預想的要晚。而 scheduleAtFixedRate 則不存在這個問題,它會按照指定的時間和頻率執行,這樣坐就會出現,同一時刻會有兩個任務在同時執行,若是,可能會發生併發問題。
上面討論的是當任務本身執行的時間大於頻率時,兩個方法不同的執行情況,還有一個情況,若是當前時間晚於我們設定的開始執行時間又會怎麼辦呢?
schedule () 會比較符合正常思維,晚了就晚了,現在開始執行就是,不存在補回的情況,但是 scheduleAtFixedRate 則會一次性補回未執行的次數。舉例來說,當前時間為 09,而我們設定的開始時間為 00 ,頻率為 3 秒,則 schedule 會在 09 執行一次,12 執行一次。而 scheduleAtFixedRate 會在 09 一次性執行 4 次,12 執行一次,後面就是正常的頻率。
下面再說幾個可能會起到錦上添花作用的方法,我們的若是想取消任務的執行,有一個方法但是分為兩個類執行,我們可以呼叫 TimeTask 中的 cancel 方法,這個方法只對當前任務有效,若是想取消全部的任務,則需要呼叫 Timer 中的 cancel 方法。
那有該如何檢視定時器 Timer 中已經被取消任務的數量呢?當然還是有方法的,那就是 Timer 中的 purge 方法。
說了這麼說,實際上我們可以看到,Timer 定時器本身還是呼叫執行緒來完成定時操作。且後臺只有一個多執行緒 TimeThread 在工作。
那 Timer 定時器有什麼缺點呢?
1 併發操作時的缺陷,這是因為 Timer 的後臺只有一個執行執行緒導致的,容易引起併發問題。
2 任務丟擲異常時缺陷。如果 TimeTask 丟擲 RuntimeException,Timer 會停止所有任務的執行。
所以以後我們在使用 Timer 定時器的時候要注意,這兩個情況,多工且併發執行的時候不要使用 Timer,複雜任務排程的時候也不要使用 Timer ,因為一個不小心出現異常了,所有任務都卡殼了。但是,Timer 定時器處理一些簡單的定是任務還是非常方便的!比方說我想實現的,定時傳送郵件。用起來就很是方便,因為這是 JDK 自帶的 API 呀!
第三種方式:使用 Java 中的專門用於定時任務管理的框架 Quartz 。(還沒學,等等吧……)
上面也說了 Timer 定時器的弊端,怎麼辦,據聽說 Quartz 可以解決這些……
後記:據我知道,Java 中定時任務也就這幾個吧,歡迎補充,有好多人說到某某框架中有定時任務,我想說的是,那不是!那是框架整合了上面說的定時任務框架,可能整合的就是 Quartz,或是 Quartz 的簡化版本……
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2236/viewspace-2819291/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java 定時任務Java
- java web定時任務JavaWeb
- Java & Go 定時任務JavaGo
- java定時任務巢狀Java巢狀
- java定時任務--Timer、TimerTaskJava
- Java編寫定時任務Java
- spring boot中的定時任務Spring Boot
- Linux系統中延時任務及定時任務Linux
- Java定時任務解決方案Java
- Java之定時任務全家桶Java
- java Quartz 定時任務管理類Javaquartz
- Java如何實現定時任務?Java
- Android 中的定時任務排程Android
- 如何用 Java 實現 Web 應用中的定時任務?JavaWeb
- 定時任務
- java springboot 實現定時器任務JavaSpring Boot定時器
- Java 定時任務技術趨勢Java
- 基於Java反射的定時任務設計Java反射
- Java中的任務超時處理Java
- Node 系統中定時任務的演化
- 使用Java實現定時任務排程Java
- Java定時任務實現優惠碼Java
- SpringBoot中併發定時任務的實現、動態定時任務的實現(看這一篇就夠了)Spring Boot
- SpringTask定時任務Spring
- Oracle定時任務Oracle
- Navicat定時任務
- schedule 定時任務
- 定時任務scheduler
- 定時任務操作
- @Scheduled 定時任務
- Linux 定時任務Linux
- Linux | 定時任務Linux
- At 、Crontabl定時任務
- crontab定時任務
- laravel定時任務Laravel
- SpringBoot定時任務Spring Boot
- springboot:定時任務Spring Boot
- 定時任務管理