您的位置:首页 > 编程语言 > Java开发

Java Timer schedule 与 scheduleAtFixedRate 比较

2017-12-09 12:42 363 查看
schedule(TimerTask task, Date firstTime, long period)

public class Run2_1 {
static public class MyTaskA extends TimerTask {

private int i = 5;
@Override
public void run() {
try {
if (i < 1) return;
System.out.println("A运行了!时间为:" + new Date());
Thread.sleep(i * 1000);
i--;
System.out.println("A结束了!时间为:" + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
Date dateRef = new Date();
timer.schedule(taskA, dateRef, 4000);//period = 4
}
}


输出结果:

A运行了!时间为:Sat Dec 09 08:56:33 CST 2017
A结束了!时间为:Sat Dec 09 08:56:38 CST 2017 //endTime - startTime = 5s > period
A运行了!时间为:Sat Dec 09 08:56:38 CST 2017 //第二次任务立即开始
A结束了!时间为:Sat Dec 09 08:56:42 CST 2017 //endTime - startTime = 4s = period
A运行了!时间为:Sat Dec 09 08:56:42 CST 2017 //第三次任务立即开始
A结束了!时间为:Sat Dec 09 08:56:45 CST 2017 //endTime - startTime = 3s < period
A运行了!时间为:Sat Dec 09 08:56:46 CST 2017 //第四次任务等待 period - (endTime - startTime ) 后开始
A结束了!时间为:Sat Dec 09 08:56:48 CST 2017 //endTime - startTime = 2s < period
A运行了!时间为:Sat Dec 09 08:56:50 CST 2017 //第五次任务等待 period - (endTime - startTime )后开始
A结束了!时间为:Sat Dec 09 08:56:51 CST 2017


归纳:

1. period 是相对上次任务的开始执行时间(startTime)而言的

2. 如果上次任务的执行时间(endTime - startTime)小于period,也即上次任务耗费时间小于间隔,则下次任务需要等待period - endTime 的时间才能开始执行

3. 而如果上次任务的执行时间(endTime - startTime)>= period,也即上次任务耗费时间大于或等于间隔,则下次任务在上次任务执行完成后立即开始执行

scheduleAtFixedRate(TimerTask task,Date firsttime,long period) 的追赶执行性

public class Run3 {
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 运行了!时间为:" + new Date());
Thread.sleep(2000);
System.out.println("1   end 运行了!时间为:" + new Date());
runCount++;
if (runCount == 9) {
timer.cancel();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
try {
MyTask1 task1 = new MyTask1();
Date startDate = new Date();
Thread.sleep(3000);//延时3s
System.out.println("字符串1时间:" + startDate.toLocaleString() + " 当前时间:"
+ new Date().toLocaleString());
//startDate 比当前时间提前3s
timer.scheduleAtFixedRate(task1, startDate, 3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


输出:

字符串1时间:2017-12-9 12:17:36 当前时间:2017-12-9 12:17:39    执行时间点分析
1 begin 运行了!时间为:Sat Dec 09 12:17:39 CST 2017    -       0
1   end 运行了!时间为:Sat Dec 09 12:17:41 CST 2017    -       2
1 begin 运行了!时间为:Sat Dec 09 12:17:41 CST 2017    -       2   --- 距离上次任务间隔2s
1   end 运行了!时间为:Sat Dec 09 12:17:43 CST 2017    -       4
1 begin 运行了!时间为:Sat Dec 09 12:17:43 CST 2017    -       4   --- 距离上次任务间隔2s
1   end 运行了!时间为:Sat Dec 09 12:17:45 CST 2017    -       6
1 begin 运行了!时间为:Sat Dec 09 12:17:45 CST 2017    -       6   --- 开始恢复正常执行,间隔为3s
1   end 运行了!时间为:Sat Dec 09 12:17:47 CST 2017    -       8
1 begin 运行了!时间为:Sat Dec 09 12:17:48 CST 2017    -       9   --- 距离上次任务间隔3s
1   end 运行了!时间为:Sat Dec 09 12:17:50 CST 2017    -       11
1 begin 运行了!时间为:Sat Dec 09 12:17:51 CST 2017    -       12  --- 距离上次任务间隔3s
1   end 运行了!时间为:Sat Dec 09 12:17:53 CST 2017    -       14
1 begin 运行了!时间为:Sat Dec 09 12:17:54 CST 2017    -       15  --- 距离上次任务间隔3s
1   end 运行了!时间为:Sat Dec 09 12:17:56 CST 2017    -       17
1 begin 运行了!时间为:Sat Dec 09 12:17:57 CST 2017    -       18
1   end 运行了!时间为:Sat Dec 09 12:17:59 CST 2017    -       20
1 begin 运行了!时间为:Sat Dec 09 12:18:00 CST 2017    -       21
1   end 运行了!时间为:Sat Dec 09 12:18:02 CST 2017    -       23


分析:

开始时间比执行时间提前了3秒

可以看到前面三次任务执行间隔都为2s,并不按照设定的延时 3s。此阶段也即为
scheduleAtFixedRate()
方法具有追赶型。他会“补充性”的执行开始时间和当前时间 时间差所对应的任务

再举个栗子:

public class Run3 {
private static Timer timer = new Timer();
private static int runCount = 0;

static public class MyTask1 extends TimerTask {
@Override
public void run() {
System.out.println("1 begin 运行了!时间为:" + new Date());
//Thread.sleep(2000);//不做延时
System.out.println("1   end 运行了!时间为:" + new Date());
runCount++;
if (runCount == 9) {
timer.cancel();
}
}
}

public static void main(String[] args) {
try {
MyTask1 task1 = new MyTask1();
Date startDate = new Date();
Thread.sleep(10000);//延时10s
System.out.println("字符串1时间:" + startDate.toLocaleString() + " 当前时间:"
+ new Date().toLocaleString());
timer.scheduleAtFixedRate(task1, startDate, 3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


输出:

字符串1时间:2017-12-9 12:39:36 当前时间:2017-12-9 12:39:46
1 begin 运行了!时间为:Sat Dec 09 12:39:46 CST 2017
1   end 运行了!时间为:Sat Dec 09 12:39:46 CST 2017
1 begin 运行了!时间为:Sat Dec 09 12:39:46 CST 2017
1   end 运行了!时间为:Sat Dec 09 12:39:46 CST 2017
1 begin 运行了!时间为:Sat Dec 09 12:39:46 CST 2017
1   end 运行了!时间为:Sat Dec 09 12:39:46 CST 2017
1 begin 运行了!时间为:Sat Dec 09 12:39:46 CST 2017
1   end 运行了!时间为:Sat Dec 09 12:39:46 CST 2017
1 begin 运行了!时间为:Sat Dec 09 12:39:48 CST 2017   --- 开始会恢复正常的时间间隔 3s
1   end 运行了!时间为:Sat Dec 09 12:39:48 CST 2017
1 begin 运行了!时间为:Sat Dec 09 12:39:51 CST 2017
1   end 运行了!时间为:Sat Dec 09 12:39:51 CST 2017
1 begin 运行了!时间为:Sat Dec 09 12:39:54 CST 2017
1   end 运行了!时间为:Sat Dec 09 12:39:54 CST 2017
1 begin 运行了!时间为:Sat Dec 09 12:39:57 CST 2017
1   end 运行了!时间为:Sat Dec 09 12:39:57 CST 2017
1 begin 运行了!时间为:Sat Dec 09 12:40:00 CST 2017
1   end 运行了!时间为:Sat Dec 09 12:40:00 CST 2017


scheduleAtFixedRate(TimerTask task,Date firsttime,long period) 发生延时

public class Run3 {
private static Timer timer = new Timer();
private static int runCount = 0;

static public class MyTask1 extends TimerTask {
@Override
public void run() {
System.out.println("1 begin 运行了!时间为:" + new Date());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1   end 运行了!时间为:" + new Date());
runCount++;
if (runCount == 5) {
timer.cancel();
}
}
}

public static void main(String[] args) {
MyTask1 task1 = new MyTask1();
Date startDate = new Date();
System.out.println("字符串1时间:" + startDate.toLocaleString() + " 当前时间:"
+ new Date().toLocaleString());
timer.scheduleAtFixedRate(task1, startDate, 3000);
}
}


输出:

字符串1时间:2017-12-10 10:14:59 当前时间:2017-12-10 10:14:59
1 begin 运行了!时间为:Sun Dec 10 10:14:59 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:15:03 CST 2017
1 begin 运行了!时间为:Sun Dec 10 10:15:03 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:15:07 CST 2017
1 begin 运行了!时间为:Sun Dec 10 10:15:07 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:15:11 CST 2017
1 begin 运行了!时间为:Sun Dec 10 10:15:11 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:15:15 CST 2017
1 begin 运行了!时间为:Sun Dec 10 10:15:15 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:15:19 CST 2017


可以看到,但 任务执行时间长与重复间隔 priod 时,则当上次任务执行完毕时,下次任务则跟着立即执行

scheduleAtFixedRate(TimerTask task,Date firsttime,long period) 不发生延时

public class Run3 {
private static Timer timer = new Timer();
private static int runCount = 0;

static public class MyTask1 extends TimerTask {
@Override
public void run() {
System.out.println("1 begin 运行了!时间为:" + new Date());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1   end 运行了!时间为:" + new Date());
runCount++;
if (runCount == 5) {
timer.cancel();
}
}
}

public static void main(String[] args) {
MyTask1 task1 = new MyTask1();
Date startDate = new Date();
System.out.println("字符串1时间:" + startDate.toLocaleString() + " 当前时间:"
+ new Date().toLocaleString());
timer.scheduleAtFixedRate(task1, startDate, 3000);
}
}


输出:

字符串1时间:2017-12-10 10:16:24 当前时间:2017-12-10 10:16:24
1 begin 运行了!时间为:Sun Dec 10 10:16:24 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:16:26 CST 2017
1 begin 运行了!时间为:Sun Dec 10 10:16:27 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:16:29 CST 2017
1 begin 运行了!时间为:Sun Dec 10 10:16:30 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:16:32 CST 2017
1 begin 运行了!时间为:Sun Dec 10 10:16:33 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:16:35 CST 2017
1 begin 运行了!时间为:Sun Dec 10 10:16:36 CST 2017
1   end 运行了!时间为:Sun Dec 10 10:16:38 CST 2017


可以看到,但任务执行时间小于任务执行间隔 priod时,下次任务的开始执行时间与上次任务的开始执行时间的间隔就是period
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java