首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >schedule和scheduleAtFixedRate有什么区别?

schedule和scheduleAtFixedRate有什么区别?
EN

Stack Overflow用户
提问于 2014-03-19 01:41:57
回答 2查看 15.4K关注 0票数 33

Timer类的这两个方法有什么区别:

代码语言:javascript
复制
schedule(TimerTask task, long delay, long period)

代码语言:javascript
复制
scheduleAtFixedRate(TimerTask task, long delay, long period)

Documentation并没有清楚地说明它们之间的区别。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-19 01:48:46

文档确实解释了其中的区别:

日程安排:

在固定延迟执行中,每次执行都是相对于上次执行的实际执行时间进行调度的。如果由于任何原因(例如垃圾收集或其他后台活动)而延迟执行,则后续执行也将延迟。

因此,假设延迟为5秒,每个任务需要2秒,您将得到

代码语言:javascript
复制
TTWWWTTWWWTTWWWTT

其中T表示任务执行1秒,W表示等待1秒。

但现在假设发生了一个长GC (由G表示),并延迟了第二个任务,第三个任务将在第二个任务开始5秒后启动,就好像长GC没有发生一样:

代码语言:javascript
复制
TTWWWGGTTWWWTTWWWTT

第三个任务在第二个任务开始5秒后开始。

scheduleAtFixedRate:

在固定速率执行中,每次执行都是相对于初始执行的调度执行时间进行调度的。如果由于任何原因(例如垃圾收集或其他后台活动)而延迟执行,则会快速连续发生两次或更多次执行,以“赶上”。

因此,使用与上面相同的延迟和相同的GC,您将得到

代码语言:javascript
复制
TTWWWGGTTWTTWWWTT

第三个任务开始3秒,而不是第二个任务后5秒,以赶上。

票数 60
EN

Stack Overflow用户

发布于 2017-07-17 01:46:29

感谢@Nizet的回答,我已经为一些想要练习和学习的人写了一个示例代码。

代码语言:javascript
复制
import java.util.Timer;
import java.util.TimerTask;

public class TimerTest {

    public static void main(String args[]){
        TimerTest.DelayTask task = new DelayTask();
        Timer timer = new Timer();
        /**
         * Use schedule or scheduletAtFixedrate and check the printed result
         */
        timer.schedule(task, 0, 5000);
        //timer.scheduleAtFixedRate(task, 0, 5000);
    }

    public static boolean stop = false;

    public static void delayOneSec(String status){
        try{
            System.out.print(status);
            Thread.sleep(1000);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    static class DelayTask extends TimerTask{
        int count = 2;

        @Override
        public void run() {
            // TODO Auto-generated method stub
            stop = true;
            for(int i = 0; i < count; i++){
                TimerTest.delayOneSec("T");
            }
            if(count == 2){
                count = 6;
            }else{
                count = 2;
            }
            stop = false;
            new PrintW().start();
        }
    }

    static class PrintW extends Thread{
        @Override
        public void run(){
            while(!stop){
                TimerTest.delayOneSec("W");
            }
        }

    }
}

任务本身将重复执行,耗时2秒或6秒。让我们看看每个场景的结果。

使用timer.schedule(task, 0, 5000);时,输出为TTWWWTTTTTTTTWWWTTTTTTTTWWWTTTTTTTT。如你所见,计时器遵循如下规则,如果任务及时完成,则等待period超时,如果当前任务持续时间超过period,则立即启动下一个任务。

使用timer.scheduleAtFixedRate(task, 0, 5000);时,输出为TTWWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTT。现在情况有点不同了。javadoc

两次或两次以上的执行将快速连续发生,以“追赶”。

在这里生效。正如您所看到的,忽略第一个TTWWW,每两个任务将打印TTTTTTTTWW,并持续10秒(两个周期)。

让我们深入研究一下Timer的源代码。

代码语言:javascript
复制
public void schedule(TimerTask task, Date firstTime, long period) {
    if (period <= 0)
        throw new IllegalArgumentException("Non-positive period.");
    sched(task, firstTime.getTime(), -period);
}


public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
    if (delay < 0)
        throw new IllegalArgumentException("Negative delay.");
    if (period <= 0)
        throw new IllegalArgumentException("Non-positive period.");
    sched(task, System.currentTimeMillis()+delay, period);
}

如您所见,在schedule方法中,period被转换为负值。让我们来看看在调度时有什么不同。

下面的代码在TimerThreadmainloop中。

代码语言:javascript
复制
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime<=currentTime)) {
    if (task.period == 0) { // Non-repeating, remove
        queue.removeMin();
        task.state = TimerTask.EXECUTED;
    } else { // Repeating task, reschedule
        queue.rescheduleMin(
        task.period<0 ? currentTime   - task.period
                      : executionTime + task.period);
           }
    }
}

这就是魔术发生的地方,对于schedule方法,下一个任务的执行时间是基于在this任务运行之前计算的currentTime。这意味着,每个任务的执行时间只与前一个任务的开始时间相关。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22486997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档