在實際應用中,有時候我們需要創建一些個延遲的、並具有週期性的任務,比如,我們希望當我們的程序啓動後每隔1小時就去做一次日誌記錄。在JDK中提供了兩種方法去創建延遲週期性任務。
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TestTimer {
public static void main(String[] args) {
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println("Start time : " + time);
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println("Now Time : " + time);
}
}; //end task
timer.schedule(task, 2000, 3000);
}
}
程序的輸出:
Start time : 21:36:08
Now Time : 21:36:10
Now Time : 21:36:13
Now Time : 21:36:16
Now Time : 21:36:19
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestScheduledThreadPoolExecutor {
public static void main(String[] args) {
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println("Start time : " + time);
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5); //創建5個執行線程
Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println("Now Time : " + time);
}
};
executor.scheduleWithFixedDelay(runnable, 2, 3, TimeUnit.SECONDS);
}
}
程序的輸出:
Start time : 22:12:25
Now Time : 22:12:27
Now Time : 22:12:30
Now Time : 22:12:33
Now Time : 22:12:36
這樣看來Timer和ScheduledThreadPoolExecutor好像沒有聲明差別,但是ScheduledThreadPoolExecutor的引入正是由於Timer類存在的一些不足,並且在JDK1.5或更高版本中,幾乎沒有利用繼續使用Timer類,下面說明Timer存在的一些缺點。
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class SingleThreadTimer {
public static void main(String[] args) {
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println("Start time : " + time);
Timer timer = new Timer();
TimerTask task1 = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println("Task1 time : " + time);
}
};
TimerTask task2 = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println("task2 time : " + time);
}
};
timer.schedule(task1, 2000, 1000);
timer.schedule(task2, 2000, 3000);
}
}
這裏定義了兩個任務,任務1,程序啓動2秒後每隔1秒運行一次,任務2,程序啓動2秒後,每隔3秒運行1次,然後讓Timer同時運行這兩個任務
Start time : 22:22:37
Task1 time : 22:22:39
task2 time : 22:22:41
Task1 time : 22:22:41
Task1 time : 22:22:42
task2 time : 22:22:44
Task1 time : 22:22:44
Task1 time : 22:22:45
task2 time : 22:22:47
Task1 time : 22:22:47
Task1 time : 22:22:48
可以分析,無論是任務1還是任務2都沒有按照我們設定的預期進行運行,造成這個現象的原因就是Timer類是單線程的。
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TestTimerTask {
public static void main(String[] args) {
System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date()));
Timer timer = new Timer();
TimerTask task1 = new TimerTask() {
@Override
public void run() {
System.out.println("1: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
};
TimerTask task2 = new TimerTask() {
@Override
public void run() {
int[] arr = {1,2,3,4,5};
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int index = (int)(Math.random()*100);
System.out.println(arr[index]);
System.out.println("2: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
};
timer.schedule(task1, 2000, 3000);
timer.schedule(task2, 2000, 1000);
}
}
程序會在運行過程中拋出數組越界異常,並且整個程序都會被終止,原來完好的任務1也被終止了。