勿以惡小而爲之,勿以善小而不爲--------------------------劉備
勸諸君,多行善事積福報,莫作惡
上一章簡單介紹了 JavaSE實現國際化操作(十五),如果沒有看過,請觀看上一章
一. 爲什麼要出現定時任務?
在實際生活和開發中,常常會遇到類似的情況, 如 1.女朋友生日那一天,發送定時消息,提醒生日快樂 2. 給某人寫郵件編寫好內容之後,在晚上10點時準時發送, 3 某天固定8點起牀,晚上10點睡覺 4.母親節,父親節時給父母發送消息。 等生活中的定時小例子 (鬧鐘,備忘錄都屬於定時)。
開發中,1. 給已經註冊的用戶,在用戶生日那天,發送生日祝福. 2. 公司員工,當入職滿一年時,增加年假至5天,入職5年時,增加年假至10天。 3.定時刪除三個月前的日誌記錄消息。 4. 定時監測網站訪問情況等開發中的定時小例子。
這些生活和開發實例,都屬於定時任務。 定時任務,是很常見的,也是很重要的。
JavaSE 階段提供了 三種方式,來實現定時任務。
JavaEE 階段,使用 Quartz 框架來實現定時任務。
二. JavaSE 階段實現定時任務
二.一 多線程 Runnable 和Thread 實現定時任務
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* Thread 多線程通過休眠時間來實現定時執行
* @author 兩個蝴蝶飛
*
*/
public class ThreadDemo {
public static void main(String []args){
//定時的時間
Long SLEEP_TIME=1000*5L;
Runnable runnable=new Runnable() {
@Override
public void run() {
while(true){
try {
//通過設置休眠,來達到定時的效果。 每5s執行一次
Thread.sleep(SLEEP_TIME);
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String localeDate=sdf.format(new Date());
System.out.println("Thread 線程:當前時間爲:"+localeDate);
} catch (InterruptedException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
}
}
};
Thread thread=new Thread(runnable);
thread.start();
}
}
控制檯打印輸出:
如果想取消定時的話, 可以定義一個全局常量flag,flag默認是true, 將 while(true) 改成 while(flag), 當取消定時時,將flag 由true 改成false 即可。
二.二 TimerTask 和 Timer 實現定時任務
二.二.一 代碼編寫
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
*
* TimerTask 和Timer 實現定時任務
* @author 兩個蝴蝶飛
*
*/
public class TaskDemo {
public static void main(String[] args) {
Timer timer=new Timer();
TimerTask task=new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String localeDate=sdf.format(new Date());
System.out.println("Task任務:當前時間爲:"+localeDate);
}
};
timer.scheduleAtFixedRate(task,0,5000);
//調用 cancel()方法來取消定時
//timer.cancel();
}
}
通過調用 Timer 對象的 scheduleAtFixedRate() 方法,來實現定時任務。
控制檯打印輸出:
二.二.二 Timer中的調度方法
task 均爲執行定時任務的對象,時間單位爲 ms.
方法簽名 | 作用 |
---|---|
schedule(TimerTask task, long delay) | 在delay ms 後執行定時任務,只執行一次 |
schedule(TimerTask task, Date time) | 在time 時間時執行定時任務,只執行一次 |
public void schedule(TimerTask task, long delay, long period) | 在delay ms後執行定時任務, 並且每隔 period 毫秒再次執行任務,會多次執行, 以固定時間 |
schedule(TimerTask task, Date firstTime, long period) | 在firstTime時間執行定時任務, 並且每隔 period毫秒再次執行任務,會多次執行, 以固定時間 |
scheduleAtFixedRate(TimerTask task, long delay, long period) | 在delay ms後執行定時任務, 並且每隔 period 毫秒再次執行任務,會多次執行, 不一定均以固定時間執行 |
scheduleAtFixedRate(TimerTask task, Date firstTime, long period) | 在firstTime時間執行定時任務, 並且每隔 period毫秒再次執行任務,會多次執行, 不一定均以固定時間執行 |
schedule()方法和 scheduleAtFixedRate()方法,是有一些區別的。
schedule()方法,假設是每5s執行一次,由5s,10s,15s,20s時執行, 但由於CPU徵用導致定時任務並沒有在5s這個時間上執行,而是在9s時執行了,延遲了4s,那麼下一次該任務執行的時間是 9+5=14s,而不是原計劃的10s. 這樣會導致可能漏掉調度的情況。
scheduleAtFixedRate()方法,假設是每5s執行一次,由5s,10s,15s,20s時執行, 但由於CPU徵用導致定時任務並沒有在5s這個時間上執行,而是在9s時執行了,延遲了4s,那麼下一次該任務執行的時間還是10s, 與原計劃一樣(會將間隔時間的period=5000 變成period=1000,但下下一次仍然是5000), 不會導致漏掉調度的情況。
故常常使用的是 scheduleAtFixedRate() 方法。
二.三 ScheduledExecutor 實現定時任務
在 java.util.concurrent 包下
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* ScheduledExecutor 實現定時調度
* @author 兩個蝴蝶飛
*
*/
public class ScheduleDemo {
public static void main(String[] args) {
//定義定時任務
Runnable runnable=new Runnable() {
@Override
public void run() {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String localeDate=sdf.format(new Date());
System.out.println("Scheduled調度:當前時間爲:"+localeDate);
}
};
//定義調度服務
ScheduledExecutorService scheduledExecutorService=Executors.newSingleThreadScheduledExecutor();
//運行, 哪個任務,開始時間,間隔時間,間隔單位
scheduledExecutorService.scheduleAtFixedRate(runnable, 0, 2, TimeUnit.SECONDS);
}
}
控制檯打印輸出:
三. JavaSE 實現調度的不足
上面的三種方式,雖然都實現了定時任務,但面對複雜多變的定時任務情況,就顯得力不從心了。
如,
-
無法實現類似 ‘每年的母親節給母親發送祝福’,‘每個月的最後一天顯示員工的本月的工作情況’,‘距離每個月10號最近的工作日發薪資’ 等非固定日期的情況。開發者不能在程序中進行判斷日期。
-
無法與當前主流框架 Spring 進行很好的整合。
-
定時任務的事務處理,需要開發者自己進行處理。
-
定時任務持久化保存
想處理好定時任務,可以學習一下 Quartz 定時任務框架。
謝謝您的觀看!!!