Java实现定时任务

在工作中不免会碰到定时任务,我将我这次编写定时任务做一个记录,

java中JDk提供了两种定时任务实现

一.Timer

Timer是最简单的一种定时任务

实现代码如下

import java.util.TimerTask;

/**
 * <p>
 * 创建一个类继承TimerTask重写run方法
 * </p>
 *
 * @author Alemand
 * @since 2018/2/26
 */
public class TimeTest extends TimerTask {

    private int i;

    public TimeTest(int i) {
        this.i = i;
    }

    /**
     * 重写自Timertask,run方法执行的就是具体的定时任务
     */
    @Override
    public void run() {
        System.out.println(i);
    }
}
/**
 * <p>
 * 创建一个类继承TimerTask重写run方法
 * </p>
 *
 * @author Alemand
 * @since 2018/2/26
 */
public class TimeTest extends TimerTask {

    private int i;

    public TimeTest(int i) {
        this.i = i;
    }

    /**
     * 重写自Timertask,run方法执行的就是具体的定时任务
     */
    @Override
    public void run() {
        System.out.println(i);
    }
}

使用Timer的核心就是Timer和TimerTask.TimerTask继承线程记录任务的状态

Timer负责时间的调度,Timer的核心实现是一个TimerThread和TaskQueue,Timer调用方法的时候就是将TimerTask的放到queue中,TimerThread是一个守护线程用来执行queue的TimerTask.这个线程会轮询所有任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread 被唤醒并执行该任务。之后 TimerThread 更新最近一个要执行的任务,继续休眠。

Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。

二.线程池 ScheduledExecutor

线程池ScheduledExecutor弥补了上面Timer的缺陷,它的设计思想每一个任务就是线程池的一个任务,因此任务是并行的,相互之间不受干扰,注意的是,只有当任务的执行时间到来时,ScheduedExecutor 才会真正启动一个线程,其余时间 ScheduledExecutor 都是在轮询任务的状态。

具体的代码如下

public class Test1 {
    public static void main(String[] args) {
        //使用Executors创建线程池
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        scheduledExecutorService.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println(1);
            }
        }, 10, TimeUnit.SECONDS);
       
    }
}

ScheduledExecutorService方法介绍

schedule(Runnable command,long delay, TimeUnit unit);
schedule(Callable command,long delay, TimeUnit unit);
上面两个方法是方法的重载一个参数都是要穿一个线程,可以是Runable,也可以是Callable,当穿Callable会将线程的
结果返回去,第二个是延迟时间,第三个参数是计时单位
scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit);
scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit);
这两个方法是周期执行方法,第一个参数是一个线程,第二个是延迟时间,第三个是周期时间,第四个计时单位
scheduleAtFixedRate与scheduleWithFixedDelay的区别是
scheduleAtFixedRate是以延迟后的执行时间为基准的举例你在12:00创建了一个延迟10分执行的任务周期时间为一个小时
那么它会在13:10.14:10 ...是以12:10分为基准加上n*周期时间执行的
scheduleWithFixedDelay是以上次任务的开始时间为基准的,举例12:00创建了一个延迟10分执行的任务周期时间为20分

那么它会在12.30.12:50 ...是以上次开始分为基准加上周期时间执行的

采用这两种方式编写定时任务是时都会有问题具体的什么问题

1.定时任务太多,线程池满了怎么办

2.当服务发生突发情况那么前的定时任务都会丢失

猜你喜欢

转载自blog.csdn.net/mypersonalsong/article/details/79369742