1.利用Timer來進行定時任務的書寫,可以通過編譯時間間隔來進行
TimerTask
TimerTask類是一個抽象類,由Timer 安排爲一次執行或重複執行的任務。它有一個抽象方法run()方法,該方法用於執行相應計時器任務要執行的操作。因此每一個具體的任務類都必須繼承TimerTask,然後重寫run()方法。
另外它還有兩個非抽象的方法:
boolean cancel():取消此計時器任務。
long scheduledExecutionTime():返回此任務最近實際執行的安排執行時間。
import java.util.Timer;
import java.util.TimerTask;
/**
* 描述:利用Timer來進行定時任務的書寫
*
* @outhor 馬銘澤
* @create 2019-06-11 9:44
*/
public class TimerTest01 {
Timer timer;
public TimerTest01(int time){
timer = new Timer();
timer.schedule(new TimerTaskTest01(), time * 1000);
}
public static void main(String[] args) {
System.out.println("timer begin....");
new TimerTest01(10);
}
}
class TimerTaskTest01 extends TimerTask {
public void run() {
System.out.println("Time's up!!!!");
}
}
但是用Timer中可能遇上兩個問題:
1、Timer管理時間延遲缺陷:
前面Timer在執行定時任務時只會創建一個線程任務,如果存在多個線程,若其中某個線程因爲某種原因而導致線程任務執行時間過長,超過了兩個任務的間隔時間,會發生一些缺陷:
2、Timer拋出異常缺陷:
如果TimerTask拋出RuntimeException,Timer會終止所有任務的運行。
解決辦法:
對於Timer的缺陷,我們可以考慮 ScheduledThreadPoolExecutor 來替代。Timer是基於絕對時間的,對系統時間比較敏感,而ScheduledThreadPoolExecutor 則是基於相對時間;Timer是內部是單一線程,而ScheduledThreadPoolExecutor內部是個線程池,所以可以支持多個任務併發執行。
2.用ScheduledExecutorService替代Timer
1、解決問題一:
public class ScheduledExecutorTest {
private ScheduledExecutorService scheduExec;
public long start;
ScheduledExecutorTest(){
this.scheduExec = Executors.newScheduledThreadPool(2);
this.start = System.currentTimeMillis();
}
public void timerOne(){
scheduExec.schedule(new Runnable() {
public void run() {
System.out.println("timerOne,the time:" + (System.currentTimeMillis() - start));
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},1000,TimeUnit.MILLISECONDS);
}
public void timerTwo(){
scheduExec.schedule(new Runnable() {
public void run() {
System.out.println("timerTwo,the time:" + (System.currentTimeMillis() - start));
}
},2000,TimeUnit.MILLISECONDS);
}
public static void main(String[] args) {
ScheduledExecutorTest test = new ScheduledExecutorTest();
test.timerOne();
test.timerTwo();
}
}
運行結果:
timerOne,the time:1003
timerTwo,the time:2005
2、解決問題二
public class ScheduledExecutorTest {
private ScheduledExecutorService scheduExec;
public long start;
ScheduledExecutorTest(){
this.scheduExec = Executors.newScheduledThreadPool(2);
this.start = System.currentTimeMillis();
}
public void timerOne(){
scheduExec.schedule(new Runnable() {
public void run() {
throw new RuntimeException();
}
},1000,TimeUnit.MILLISECONDS);
}
public void timerTwo(){
scheduExec.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("timerTwo invoked .....");
}
},2000,500,TimeUnit.MILLISECONDS);
}
public static void main(String[] args) {
ScheduledExecutorTest test = new ScheduledExecutorTest();
test.timerOne();
test.timerTwo();
}
}
遇上異常可以拋出,然後可以繼續線程
運行結果:
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
........................