方法schedule和方法scheduleAtFixedRate都會按順序執(zhí)行,所以不要考慮非線程安全的情況。
方法schedule和方法scheduleAtFixedRate只在于不延時的情況。
使用schedule方法:如果執(zhí)行任務(wù)的時間沒有被延時,那么下一次任務(wù)的執(zhí)行時間參考的是上一次任務(wù)的“開始”時的時間來計算。
使用scheduleAtFixedRate方法:如果執(zhí)行任務(wù)的時間沒有被延時,那么下一次任務(wù)的執(zhí)行時間參考的是上一次任務(wù)的“結(jié)束”時的時間來計算。
延時的情況則沒有區(qū)別,也就是使用schedule或scheduleAtFixedRate方法都是如果執(zhí)行任務(wù)的時間被延時,那么下一次任務(wù)的執(zhí)行時間參考的是上一次任務(wù)“結(jié)束”時的時間來計算。
1. 測試schedule方法任務(wù)不延時
/**
* @author wuyoushan
* @date 2017/3/20.
*/
public class Run {
private static Timer timer=new Timer();
private static int runCount=0;
static public class MyTask1 extends TimerTask {
@Override
public void run() {
try{
System.out.println("1 begin 運(yùn)行了!時間為:"+new Date());
Thread.sleep(1000);
System.out.println("1 end 運(yùn)行了!時間為:"+new Date());
runCount++;
if (runCount==5){
timer.cancel();
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
MyTask1 task = new MyTask1();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString="2017-05-19 08:44:00";
Date dateRef=sdf.parse(dateString);
System.out.println("字符串時間:"+dateRef.toString()+"當(dāng)前時間:"+new Date().toString());
timer.schedule(task,dateRef,3000);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
程序的運(yùn)行結(jié)果為:
字符串時間:Fri May 19 08:44:00 CST 2017當(dāng)前時間:Mon May 22 08:12:39 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:12:39 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:12:40 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:12:42 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:12:43 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:12:45 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:12:46 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:12:48 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:12:49 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:12:51 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:12:52 CST 2017
控制臺大印的結(jié)果證明,在不延遲的情況下,如果執(zhí)行任務(wù)的時間沒有被延時,則下一次執(zhí)行任務(wù)的時間是上一次任務(wù)的開始時間加上delay時間
2. 測試schedule方法任務(wù)
/**
* @author wuyoushan
* @date 2017/3/20.
*/
public class Run {
private static Timer timer=new Timer();
private static int runCount=0;
static public class MyTask1 extends TimerTask {
@Override
public void run() {
try{
System.out.println("1 begin 運(yùn)行了!時間為:"+new Date());
Thread.sleep(5000);
System.out.println("1 end 運(yùn)行了!時間為:"+new Date());
runCount++;
if (runCount==5){
timer.cancel();
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
MyTask1 task = new MyTask1();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString="2017-05-20 08:44:00";
Date dateRef=sdf.parse(dateString);
System.out.println("字符串時間:"+dateRef.toString()+"當(dāng)前時間:"+new Date().toString());
timer.schedule(task,dateRef,2000);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
程序的運(yùn)行結(jié)果為:
字符串時間:Sat May 20 08:44:00 CST 2017當(dāng)前時間:Mon May 22 08:23:35 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:23:35 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:23:40 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:23:40 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:23:45 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:23:45 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:23:50 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:23:50 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:23:55 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:23:55 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:24:00 CST 2017
從控制臺打印的結(jié)果來看,如果執(zhí)行任務(wù)的時間被延遲,那么下一次任務(wù)的執(zhí)行時間以上一次任務(wù)“結(jié)束”時的時間為參考計算
3. 測試scheduleAtFixedRate方法任務(wù)不延時
/**
* @author wuyoushan
* @date 2017/3/20.
*/
public class Run {
private static Timer timer=new Timer();
private static int runCount=0;
static public class MyTask1 extends TimerTask {
@Override
public void run() {
try{
System.out.println("1 begin 運(yùn)行了!時間為:"+new Date());
Thread.sleep(2000);
System.out.println("1 end 運(yùn)行了!時間為:"+new Date());
runCount++;
if (runCount==5){
timer.cancel();
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
MyTask1 task = new MyTask1();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString="2017-05-20 08:44:00";
Date dateRef=sdf.parse(dateString);
System.out.println("字符串時間:"+dateRef.toString()+"當(dāng)前時間:"+new Date().toString());
timer.schedule(task,dateRef,3000);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
程序的運(yùn)行結(jié)果為:
字符串時間:Sat May 20 08:44:00 CST 2017當(dāng)前時間:Mon May 22 08:25:46 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:25:46 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:25:48 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:25:49 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:25:51 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:25:52 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:25:54 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:25:55 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:25:57 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:25:58 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:26:00 CST 2017
控制臺打印的結(jié)果證明,如果執(zhí)行任務(wù)的時間沒有被延遲時,則下一次執(zhí)行任務(wù)的時間是上一次任務(wù)的開始時間加上delay時間。
4. 測試scheduleAtFixedRate方法任務(wù)延時
/**
* @author wuyoushan
* @date 2017/3/20.
*/
public class Run {
private static Timer timer=new Timer();
private static int runCount=0;
static public class MyTask1 extends TimerTask {
@Override
public void run() {
try{
System.out.println("1 begin 運(yùn)行了!時間為:"+new Date());
Thread.sleep(5000);
System.out.println("1 end 運(yùn)行了!時間為:"+new Date());
runCount++;
if (runCount==5){
timer.cancel();
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
MyTask1 task = new MyTask1();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString="2017-05-20 08:44:00";
Date dateRef=sdf.parse(dateString);
System.out.println("字符串時間:"+dateRef.toString()+"當(dāng)前時間:"+new Date().toString());
timer.scheduleAtFixedRate(task,dateRef,2000);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
程序的運(yùn)行結(jié)果為:
字符串時間:Sat May 20 08:44:00 CST 2017當(dāng)前時間:Mon May 22 08:46:03 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:46:03 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:46:08 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:46:08 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:46:13 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:46:13 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:46:18 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:46:18 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:46:23 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:46:23 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:46:28 CST 2017
從控制臺打印的結(jié)果來看,如果執(zhí)行任務(wù)的時間被延遲時,那么下一次任務(wù)的執(zhí)行時間以上一次任務(wù)“結(jié)束”時的時間為參考來計算。
5. 驗證schedule方法不具有追趕執(zhí)行性
/**
* @author wuyoushan
* @date 2017/3/20.
*/
public class Run {
private static Timer timer=new Timer();
static public class MyTask1 extends TimerTask {
@Override
public void run() {
System.out.println("1 begin 運(yùn)行了!時間為:"+new Date());
System.out.println("1 end 運(yùn)行了!時間為:"+new Date());
}
}
public static void main(String[] args) {
try {
MyTask1 task = new MyTask1();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString="2017-05-20 08:44:00";
Date dateRef=sdf.parse(dateString);
System.out.println("字符串時間:"+dateRef.toString()+"當(dāng)前時間:"+new Date().toString());
timer.schedule(task,dateRef,5000);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
程序的運(yùn)行結(jié)果為:
字符串時間:Sat May 20 08:44:00 CST 2017當(dāng)前時間:Mon May 22 08:39:29 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:39:29 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:39:29 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:39:34 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:39:34 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:39:39 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:39:39 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:39:44 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:39:44 CST 2017
6. 驗證scheduleAtFixedRate方法具有追趕執(zhí)行性
/**
* @author wuyoushan
* @date 2017/3/20.
*/
public class Run {
private static Timer timer=new Timer();
static public class MyTask1 extends TimerTask {
@Override
public void run() {
System.out.println("1 begin 運(yùn)行了!時間為:"+new Date());
System.out.println("1 end 運(yùn)行了!時間為:"+new Date());
}
}
public static void main(String[] args) {
try {
MyTask1 task = new MyTask1();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString="2017-05-20 08:44:00";
Date dateRef=sdf.parse(dateString);
System.out.println("字符串時間:"+dateRef.toString()+"當(dāng)前時間:"+new Date().toString());
timer.scheduleAtFixedRate(task,dateRef,2000);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
程序的運(yùn)行結(jié)果為:
end 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 begin 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
1 end 運(yùn)行了!時間為:Mon May 22 08:52:24 CST 2017
兩個時間段內(nèi)所對應(yīng)的Task任務(wù)被“補(bǔ)充性”執(zhí)行了,這就是Task任務(wù)追趕執(zhí)行的特性。
摘選自 java多線程核心編程技術(shù)-5.1.5