周期性定时任务

时间:2022-09-18 16:55:13

周期性定时任务

一、业务场景

  Web项目开发中少不了需要使用定时任务来处理一些工作,比如定时更改某些数据的状态,定时进行统计操作等等。

自己以前参与开发过的一些系统中还有一些专门的定时任务处理子系统,用来根据具体的业务需要实现一些非常复杂的

定时任务处理操作。有的定时任务只需要执行一次,比如手机上设置的某一天某人结婚的定时闹钟提醒;有的任务需要

重复的执行,比如上班日早上起床时的闹钟。今天要分享的定时任务处理操作只针对特定场景,就是周期性循环执行的

任务。

二、实现方案

看过阿里巴巴开源的Java开发手册的同学都知道,里面关于多线程的章节,写了这么一条,

【强制】多线程并行处理定时任务时,Timer 运行多个 TimeTask 时,只要其中之一没有捕获

抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService 则没有这个问题。

 周期性定时任务

今天要讲的内容就也是采用这种方式来实现的,使用ScheduledExecutorService这个类。首先创建一个单独的服务service类,

类似于Service的实现类比如ServiceOneImpl,在这个类中写一个具体的方法,方法里面就是需要执行的具体任务的代码。真实

的开发中可以直接使用Service接口调用即可,示例代码如下:

@Slf4j

@Service

public class ServiceOneImpl  {

    public void doTaskOne() {

        log.info("执行任务一");

    }

}

然后写一个任务类,比如TaskOne这个类,让其实现Runnable接口,然后重写run方法。并且在这个类中,注入 ServiceOneImpl这个类,

然后在run方法中调用需要执行的doTaskOne()方法,示例代码如下:

@Component

public class TaskOne implements Runnable{

    @Resource

    private ServiceOneImpl serviceOneImpl;

    @Override

    public void run() {

        this.serviceOneImpl.doTaskOne();

    }

}

最后一步是写一个具体的定时任务执行类,用来统一管理所有需要执行的定时任务操作,并且需要注入ScheduledExecutorService

创建多个线程,使用不同的线程去执行不同的任务。示例代码如下:

@Slf4j

@Component

public class TimingTaskScheduler {

    @Resource

    private TaskOne taskOne;

// 创建20个线程

    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(20);

 

    @PostConstruct

    public void initialize() {

        // 参数一为需要执行的任务类 参数二为延迟时间 参数三为执行周期 参数四为时间单位

        executorService.scheduleWithFixedDelay(taskOne, 1000L, 1000L, TimeUnit.MILLISECONDS);

    }

}

到此这个定时任务的代码就完成了。这里面使用到了一个注解@PostConstruct,被这个注解标识的方法在服务器加载Servlet

时候运行,并且只会被服务器调用一次。可以参考博文 https://www.cnblogs.com/YuyuanNo1/p/8184003.html 。当服务器启动

的时候,就会触发 initialize() 这个方法执行一次,然后就会触发ScheduledExecutorService 一直不断地去执行里面的定时任务。

scheduleWithFixedDelay方法需要四个参数,第一个参数是需要执行的定时任务类,第二个参数是项目启动后的延迟执行时间,

第三个参数是执行的间隔周期,第四个参数是时间单位。真实项目中后面的两个参数都可以统一的写在一个配置文件当中,

然后使用配置文件来统一的进行设置延迟执行时间,执行周期,或者是是否执行的开关等等。

执行效果如下:

 周期性定时任务

执行的线程也是不一样的,符合实际的预期,利用多线程来进行执行。目前已经使用这种方式来处理的一些定时任务有:

.a.定时更新字典表缓存数据的任务;

.b.定时更新某张重要的表缓存数据的任务;

.c.定时更新某个接口查询缓存数据的任务;

.d.定时处理某统计操作的任务;

.e.定时处理其他复杂计算的任务;

有需要的小伙伴可以考虑使用这种方式来进行处理,阿里巴巴都推荐这么使用。有其他更好建议的小伙伴欢迎留言谈论。