Timer
- Timer類的主要作用就是設定計劃任務,但封裝任務的類卻是TimerTask類
- 執行計劃任務的程式碼要放人TimerTask的子類中,因為TimerTask是一個抽象類。而且要重寫其run方法 因為這是一個抽象方法.
常見問題
- 任務執行完了, 但程序並沒有銷燬,
- 通過原始碼檢視構造方法可以得知,建立一個 Timer就是啟動一個新的執行緒,這個新啟動的執行緒並不是守護執行緒,它一直在執行。
- 如果想要將其變為守護執行緒就在初始化timer的時候傳入一個true
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
Timer timer = new Timer(true);
Task task = new Task();
timer.schedule(task, 1000);
Thread.sleep(1000);
}
}
class Task extends TimerTask {
@Override
public void run() {
System.out.println("Listen");
}
}
- 如果我們定的執行任務的時間在未來, 這種會在將來正常執行, 如果我們定的任務在過去, 那麼這個任務就立刻執行.
- TimerTask是以佇列的方式一個一個被順序執行的,所以執行的時間有可能和預期的時間不一致,因為前面的任務有可能消耗的時間較長,則後面的任務執行的時間也會被延遲。
方法schedule(Timer Task task, long delay)
- 該方法的作用是以執行schedule(TimerTasktask,long delay)方法當前的時間為參考時間,在此時間基礎上延遲指定的毫秒數delay後執行一次TimerTask任務。
- 演示
public class Demo2 {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("執行時間: " + new Date().toString());
System.out.println("l love listen");
}
};
System.out.println("此時: " + new Date().toString());
timer.schedule(timerTask, 1000);
}
}
方法schedule(Timer Task task, long delay, long period)
- 該方法的作用是以執行schedule ( TimerTask task, long delay, long period)方法當前的時間為參考時間,在此時間基礎上延遲指定的毫秒數delay,再以某一間隔period時間無限次數地執行某一任務。
- 演示
public class Demo3 {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("執行時間" + new Date().toString());
System.out.println("l love listen");
}
};
timer.schedule(timerTask, 1000, 1000);
}
}
- 凡是使用方法中帶有period引數的,都是無限迴圈執行TimerTask中的任務。
cancel方法
TimerTask類的cancel()方法
- TimerTask類中的cancel方法的作用是將自身從任務佇列中清除。
public class Demo4 {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
volatile int count = 0;
@Override
public void run() {
System.out.println("執行時間" + new Date().toString());
System.out.println("l love listen");
count++;
if (count == 3) {
System.out.println("執行cancel");
this.cancel();
}
}
};
timer.schedule(timerTask, 1000, 1000);
}
}
- TimerTask類的cancel()方法是將自身從任務佇列中被移除,其他任務不受影響。
Timer類的cancel()方法
- 和TimerTask類中的cancel() 方法清除自身不同,Timer 類中的cancel()方法的作用是將任務佇列中的全部任務清空。
public class Demo5 {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
volatile int count = 0;
@Override
public void run() {
System.out.println("A 執行時間" + new Date().getTime());
System.out.println("l love listen");
count++;
if (count == 3) {
System.out.println("執行timer.cancel");
timer.cancel();
}
}
};
TimerTask timerTask1 = new TimerTask() {
@Override
public void run() {
System.out.println("B 執行時間" + new Date().getTime());
System.out.println("l love swy");
}
};
timer.schedule(timerTask, 1000, 1000);
timer.schedule(timerTask1, 500, 500);
}
}
- 全部任務都被清除,並且程序被銷燬,按鈕由紅色變成灰色。
timer.cancel的最常見一個問題
- Timer類中的cancel()如果執行了, 表示這個定時器就用不成了, 所以即使你再往定時器里加任務, 也是不能執行的
public class Demo6 {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("A 執行時間" + new Date().getTime());
System.out.println("l love listen");
}
};
TimerTask timerTask1 = new TimerTask() {
@Override
public void run() {
System.out.println("B 執行時間" + new Date().getTime());
System.out.println("l love swy");
}
};
while (true) {
timer.schedule(timerTask, 1000, 1000);
timer.schedule(timerTask1, 500, 500);
timer.cancel();
}
}
}
對比schedule和scheduleAtFixedRate方法
- 方法schedule和方法scheduleAtFixedRate都會按順序執行,所以不要考慮非執行緒安全的情況。方法schedule和scheduleAtFixedRate主要的區別只在於不延時的情況。使用schedule方法:如果執行任務的時間沒有被延時,那麼下一次任務的執行時間參考的是上一次任務的「開始"時的時間來計算。
使用scheduleAtFixedRate方法:如果執行任務的時間沒有被延時,那麼下一次任務的執行時間參考的是上一次任務的「結束」時的時間來計算。 - 延時的情況則沒有區別,也就是使用schedule或scheduleAtFixedRate方法都是如果執行任務的時間被延時,那麼下一次任務的執行時間參考的是上一次任務「結束」時的時間來計算。
- schedule方法不具有追趕性, 而scheduleAtFixedRate具有追趕性, 追趕性就是如果我們定的是迴圈執行的任務, 且定的任務在將來, 那麼使用schedule不會彌補時間上的空缺, 而使用scheduleAtFixedRate會補充執行, 把欠下的都執行回來.