TimerTask.cancel() 与 Timer.cancel() 的区别

        TimerTask.cancel() 与 Timer.cancel() 都可以理解为清除任务队列中的任务。看源码

        TimerTask.cancel() 

    /**
     * Cancels this timer task.  If the task has been scheduled for one-time
     * execution and has not yet run, or has not yet been scheduled, it will
     * never run.  If the task has been scheduled for repeated execution, it
     * will never run again.  (If the task is running when this call occurs,
     * the task will run to completion, but will never run again.)
     *
     * <p>Note that calling this method from within the <tt>run</tt> method of
     * a repeating timer task absolutely guarantees that the timer task will
     * not run again.
     *
     * <p>This method may be called repeatedly; the second and subsequent
     * calls have no effect.
     *
     * @return true if this task is scheduled for one-time execution and has
     *         not yet run, or this task is scheduled for repeated execution.
     *         Returns false if the task was scheduled for one-time execution
     *         and has already run, or if the task was never scheduled, or if
     *         the task was already cancelled.  (Loosely speaking, this method
     *         returns <tt>true</tt> if it prevents one or more scheduled
     *         executions from taking place.)
     */
    public boolean cancel() {
        synchronized(lock) {
            boolean result = (state == SCHEDULED);
            state = CANCELLED;
            return result;
        }
    }

        Timer.cancel(): 

    /**
     * Terminates this timer, discarding any currently scheduled tasks.
     * Does not interfere with a currently executing task (if it exists).
     * Once a timer has been terminated, its execution thread terminates
     * gracefully, and no more tasks may be scheduled on it.
     *
     * <p>Note that calling this method from within the run method of a
     * timer task that was invoked by this timer absolutely guarantees that
     * the ongoing task execution is the last task execution that will ever
     * be performed by this timer.
     *
     * <p>This method may be called repeatedly; the second and subsequent
     * calls have no effect.
     */
    public void cancel() {
        synchronized(queue) {
            thread.newTasksMayBeScheduled = false;
            queue.clear();
            queue.notify();  // In case queue was already empty.
        }
    }

        从源码中可以看出,TimerTask.cancel() 只是将当前正在执行的任务终止,state = CANCELLED,return true;如果当前任务已经执行结束,也是将当前任务终止,return false。由此我们也可以看出,当同一项任务调用多次 .cancel() 方法时,该方法只会有效执行一次。而Timer.cancel() 是将当前定时任务中的所有正在运行的任务都清除,使timer没有可执行的任务。所以两者的区别之处在TimerTask.cancel() 只是将当前任务终止,也可以理解为从定时任务(任务队列)中清除掉,但实际上并没有对Timer进行任何操作,所以在调用 TimerTask.cancel() 时,Timer定时任务(任务队列)中的其它任务还是正常执行,不会影响其它任务的正常执行而Timer.cancel() 是将整个定时任务(任务队列)的中的所有任务全部清除

       是不是调用了cancel()后任务会立即结束呢?我们从TimerTask.cancel源码的注释中也可以看到,If the task is running when this call occurs, the task will run to completion, but will never run again. 大概意思就是 当调用TimerTask.cancel() 方法时,该任务正在运行中,这项任务会正常运行到结束,但不会再次运行。同样的在Timer.cancel源码的注释中也可以看到一个类似的解释Does not interfere with a currently executing task (if it exists)翻译为中文大概就是 不干扰当前正在运行的任务(如果存在)。说明当调用cancel()方法后,当前正在运行的任务还能正常运行下去,还有一口气能把这项任务执行完毕,当任务执行完毕后,下次不会再执行,而没有开始执行的任务也不会执行

测试

测试1:task1和task2都不执行cancel()

public class TestTimerCancel {

    public static void main(String args[]) throws ParseException, InterruptedException {
        Timer timer = new Timer();
        TimerTask task1 =  new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务执行时间1:" + this.scheduledExecutionTime());
                // this.cancel();
                // timer.cancel();
            }
        };
        TimerTask task2 =  new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务执行时间2:" + this.scheduledExecutionTime());
                // this.cancel();
                // timer.cancel();
            }
        };
        
        long delay1 = 1000;      // 任务延迟毫秒数
        long delay2 = 2000;      // 任务延迟毫秒数
        long period = 1000;      // 任务间隔毫秒数
        timer.schedule(task1, delay1, period);
        timer.schedule(task2, delay2, period);
    }
}

测试结果:两个任务正常执行

任务执行时间1:1547991032207
任务执行时间2:1547991033208
任务执行时间1:1547991033208
任务执行时间1:1547991034209
任务执行时间2:1547991034209
任务执行时间2:1547991035224
任务执行时间1:1547991035224
任务执行时间1:1547991036225
任务执行时间2:1547991036225
任务执行时间2:1547991037226
任务执行时间1:1547991037226
任务执行时间1:1547991038227
任务执行时间2:1547991038227

测试2:仅task1调用TimerTask.cancel()

TimerTask task1 =  new TimerTask() {
    @Override
    public void run() {
        System.out.println("任务执行时间1:" + this.scheduledExecutionTime());
        this.cancel();
    }
};

测试结果:task1只执行了1次,调用TimerTask.cancel()不影响其它任务的正常执行

任务执行时间1:1547991235852
任务执行时间2:1547991236854
任务执行时间2:1547991237857
任务执行时间2:1547991238859
任务执行时间2:1547991239860
任务执行时间2:1547991240875
任务执行时间2:1547991241890
任务执行时间2:1547991242895
任务执行时间2:1547991243900
任务执行时间2:1547991244906

测试3:仅task1调用Timer.cancel()

TimerTask task1 =  new TimerTask() {
    @Override
    public void run() {
        System.out.println("任务执行时间1:" + this.scheduledExecutionTime());
        timer.cancel();
    }
};

测试结果:仅task1执行了一次,task2没有执行。

任务执行时间1:1547991575545

 测试4:仅task2调用TimerTask.cancel()

TimerTask task2 =  new TimerTask() {
    @Override
    public void run() {
        System.out.println("任务执行时间2:" + this.scheduledExecutionTime());
        this.cancel();
    }
};

测试结果:task2仅执行了一次,task1正常进行固定延迟执行

任务执行时间1:1547991944113
任务执行时间2:1547991945126
任务执行时间1:1547991945126
任务执行时间1:1547991946130
任务执行时间1:1547991947144
任务执行时间1:1547991948147
任务执行时间1:1547991949161
任务执行时间1:1547991950162
任务执行时间1:1547991951175

测试5:仅task2调用Timer.cancel()

TimerTask task2 =  new TimerTask() {
    @Override
    public void run() {
        System.out.println("任务执行时间2:" + this.scheduledExecutionTime());
        timer.cancel();
    }
};

测试结果:task1 和task2都仅执行了一次。由于task1早于task2执行,task2在执行时task1处于执行完毕或者执行中,所以task2执行完后,整个任务队列清除。task2仅能执行一次,task1的执行次数跟task2执行结束时间有关,task2执行结束时间越晚task1执行次数越多。

任务执行时间1:1547992056180
任务执行时间2:1547992057187

测试6:task1调用TimerTask.cancel(),task2调用Timer.cancel()

TimerTask task1 =  new TimerTask() {
    @Override
    public void run() {
        System.out.println("任务执行时间1:" + this.scheduledExecutionTime());
        this.cancel();
        // timer.cancel();
    }
};
TimerTask task2 =  new TimerTask() {
    @Override
    public void run() {
        System.out.println("任务执行时间2:" + this.scheduledExecutionTime());
        // this.cancel();
        timer.cancel();
    }
};

测试结果:task1和task2都仅执行一次

任务执行时间1:1547992543756
任务执行时间2:1547992544753

测试7:task1调用Timer.cancel(),task2调用TimerTask.cancel()

TimerTask task1 =  new TimerTask() {
    @Override
    public void run() {
        System.out.println("任务执行时间1:" + this.scheduledExecutionTime());
        // this.cancel();
        timer.cancel();
    }
};
TimerTask task2 =  new TimerTask() {
    @Override
    public void run() {
        System.out.println("任务执行时间2:" + this.scheduledExecutionTime());
        this.cancel();
        // timer.cancel();
    }
};

测试结果:仅task1执行了1次

任务执行时间1:1547992633651

猜你喜欢

转载自blog.csdn.net/ShenDaiSun/article/details/86565311