[Logic of Java programming] Timing tasks

Timer 和 TimerTask

Basic usage

TimerTask represents a timed task. It is an abstract class that implements Runnable. Specific timed tasks need to inherit this class and implement the run method.
Timer is a concrete class, which is responsible for the scheduling and execution of timed tasks. The main methods are:

// 在指定绝对时间time运行任务task
public void schedule(TimerTask task, Date time);
// 在当前时间延时delay毫秒后运行任务task
public void schedule(TimerTask task, long delay);

// 固定延时重复执行,第一次计划执行时间为firstTime,如果firstTime小于当前时间,则立即执行
// 后一次的计划执行时间为前一次“实际执行”时间加上period
public void schedule(TimerTask task, Date firstTime, long period);
// 固定延时重复执行,第一次计划执行时间为当前时间加上delay毫秒
public void schedule(TimerTask task, long delay, long period);

// 固定频率重复执行。第一次计划执行时间为firstTime,如果firstTime小于当前时间,则立即执行
// 后一次的计划执行时间为前一次“计划执行”时间加上period
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period);
// 固定频率重复执行。第一次计划执行时间为当前时间加上delay毫秒
public void scheduleAtFixedRate(TimerTask task, long delay, long period);

The difference between fixed delay and fixed frequency: Both are executed repeatedly, but the relative time of the next task execution is different. Fixed delay It is calculated based on the "actual" execution time of the last task. If the last execution time is delayed for some reason, then the task is also delayed this time.

Basic example

public class TimerFixedDelay {
    static class LongRunningTask extends TimerTask {
        @Override
        public void run() {
            try {
                System.out.println("start sleep");
                Thread.sleep(5000);
                System.out.println("sleep over");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static class FixedDelayTask extends TimerTask {
        @Override
        public void run() {
            System.out.println("FixedDelayTask:" + System.currentTimeMillis());
        }
    }
    static class FixedRateTask extends TimerTask {
        @Override
        public void run() {
            System.out.println("FixedRateTask:" + System.currentTimeMillis());
        }
    }
    public static void main(String[] args) {
        Timer timer = new Timer();
        // 延时10毫秒后执行,只执行一次,但耗时5秒
        timer.schedule(new LongRunningTask(), 10);
        // 延时100毫秒后执行,相对于上次实际执行时间,每隔2秒执行一次
        timer.schedule(new FixedDelayTask(), 100, 2000);
        // 延时100毫秒后执行,相对于上次计划执行时间,每隔1秒执行一次,
        timer.scheduleAtFixedRate(new FixedRateTask(), 100, 1000);
    }
}

Through this example, it is found that the second and third tasks will only start running after the first task has finished running.
At the same time, the difference between fixed delay and fixed frequency can be seen. The second task is fixed delay, which starts to run after the first task finishes running, once every 2 seconds. The third task is a fixed frequency, which runs after the first task runs, but it will make up for the number of times that it did not run before, and it will run 5 times at a time.

Fundamental

Timer is mainly composed of two parts: task queue and Timer thread.
The task queue is a priority queue implemented based on the heap. The priority queue is arranged according to the next execution time. The
Timer thread is responsible for executing all timing tasks. A Timer object has only one Timer thread, so the task will be delayed.

For tasks with a fixed delay, the delay is relative to the current time before the task is executed, not after the task is executed.

For tasks with a fixed frequency, the delay is relative to the first plan

infinite loop

A Timer object has only one Timer thread, which means that the timing task cannot take too long, nor can it loop infinitely.

exception handling

When executing the run method of any task, once the run throws an exception, the Timer thread will exit, so that all timed tasks will be canceled

summary

  • There is only one thread running in the background
  • After a task with a fixed frequency is delayed, it may be executed multiple times immediately, and the number of times will not be enough.
  • The delay of a fixed-delay task is relative to the time before the task is executed
  • Do not use infinite loops in timed tasks, which will cause subsequent tasks to fail to execute
  • An unhandled exception of a scheduled task will cause all scheduled tasks to be cancelled

ScheduledExecutorService

Basic usage

ScheduledExecutorService is an interface

public interface ScheduledExecutorService extends ExecutorService { 
    // 单次执行,在指定延时delay后运行command
    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
    // 单次执行,在指定延时delay后运行callable
    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
    // 固定频率重复执行
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);
    // 固定延时重复执行
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);
}

Return type ScheduledFuture, which is an interface that extends Future and Delayed.
For tasks with a fixed delay, it is calculated from the time the task is executed. The first execution is the current time + initialDelay, the second is the end of the first task execution, and then the delay is added
. For tasks with a fixed frequency, the first The second execution time is the current time + initialDelay, the second time is the current time + initialDelay + period

The main implementation class of ScheduledExecutorService is ScheduledTheradPoolExecutor, which is a subclass of thread pool ThreadPoolExecutor. Its task queue is an unbounded priority queue, so the maximum number of threads has no effect on it.
The factory class Executors provides some methods to create ScheduledTheradPoolExecutor

// 单线程的定时任务执行服务
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}

public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1, threadFactory));
}
// 多线程的定时任务执行服务
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
    return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}

summary

  • Behind the thread pool, there can be multiple threads to perform tasks
  • Set the next execution time after the task is executed, which is more reasonable for tasks with a fixed delay
  • The thread of task execution will encounter all exceptions in the process of ordinary task execution. The exception of a scheduled task will not affect other scheduled tasks. However, the task in which the exception occurs (even a repetitive task) will not be scheduled again.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325875018&siteId=291194637