From Gossip@Openhome

Java Gossip: Fixed-delay Execution 與 Fixed-rate Execution

對於Timer,要將排定時間與任務真正執行時間分別看待。

Timer的schedule()方法在排程時,是採用Fixed- delay execution的方式。也就是如果這次run()方法在週期時間內執行完畢,則下次run()就如期排程。如果這次run()方法無法在週期時間內完 成,則接下來的任務排定就會被拖延,等到上次任務完成後立即排定並執行。

如果想取得TimerTask的排定時間,則可以使用scheduledExecutionTime(),例如:
  • DateTask.java
package onlyfun.caterpillar;

import java.util.*;

public class DateTask extends TimerTask {
public void run() {
System.out.println("任務排定時間:" + new Date(scheduledExecutionTime()));
System.out.println("任務執行時間:" + new Date() + "\n");
try {
Thread.sleep(5000);
}
catch(InterruptedException e) {
}
}
}

如果您使用以下的程式片段來進行排程:
        Timer timer = new Timer();
        timer.schedule(new DateTask(), 1000, 3000);

由於在run()方法中,執行會超出所排定的週期,因此每次的下一次工作都被延遲,在上次工作完成後立即執行:

任務排定時間:Fri Jan 19 11:21:32 CST 2007
任務執行時間:Fri Jan 19 11:21:32 CST 2007

任務排定時間:Fri Jan 19 11:21:37 CST 2007
任務執行時間:Fri Jan 19 11:21:37 CST 2007

任務排定時間:Fri Jan 19 11:21:42 CST 2007
任務執行時間:Fri Jan 19 11:21:42 CST 2007

任務排定時間:Fri Jan 19 11:21:47 CST 2007
任務執行時間:Fri Jan 19 11:21:47 CST 2007

任務排定時間:Fri Jan 19 11:21:52 CST 2007
任務執行時間:Fri Jan 19 11:21:52 CST 2007


Timer還有另一個scheduleAtFixedRate()方法,可以讓您採用Fix-rate Execution。也就是如果這次run()方法在週期時間內執行完畢,則下次run()就如期排程。如果這次run()方法無法在週期時間內完成,則 接下來的任務排定不會被拖延,但真正的執行要等到上次任務完成後執行。

如果您使用以下的程式片段來進行排程:
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new DateTask(), 1000, 3000);

在run()方法中,執行會超出所排定的週期,但Timer不管,仍舊照週期排程,而真正的執行則等到上次任務完成後執行:
任務排定時間:Fri Jan 19 11:20:06 CST 2007
任務執行時間:Fri Jan 19 11:20:06 CST 2007

任務排定時間:Fri Jan 19 11:20:09 CST 2007
任務執行時間:Fri Jan 19 11:20:11 CST 2007

任務排定時間:Fri Jan 19 11:20:12 CST 2007
任務執行時間:Fri Jan 19 11:20:16 CST 2007

任務排定時間:Fri Jan 19 11:20:15 CST 2007
任務執行時間:Fri Jan 19 11:20:21 CST 2007

任務排定時間:Fri Jan 19 11:20:18 CST 2007
任務執行時間:Fri Jan 19 11:20:26 CST 2007