Java Timer schedule 与 scheduleAtFixedRate 比较

  • 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

猜你喜欢

转载自blog.csdn.net/haha_zhan/article/details/78758515
今日推荐