当前位置: 代码迷 >> 综合 >> spring-ScheduledExecutorService+TimeTask-定时器实现
  详细解决方案

spring-ScheduledExecutorService+TimeTask-定时器实现

热度:30   发布时间:2024-01-13 02:34:03.0

问题场景

需求:每隔2小时抓取集群固定文件夹下的数据包进行分析产生报告。

实现方式

TimerTask使用单线程执行方式,当定时器遇到异常下次便不会执行,但可以用线程池调度弥补。
1、spring+ScheduledExecutorService+TimeTask
2、使用quartz-1.8.5.jar

解决步骤

a 编写任务类
b 编写监听类
c 用ScheduledExecutorService调用任务

a 编写任务类

package com.xxx.awk.listener;
import com.xxx.awk.service.*;
import lombok.extern.slf4j.Slf4j;/**** @author: youxingyang* @date: 2018/8/30 9:16*/
@Slf4j
public class Task extends TimerTask {private SampleService sampleService;private String env;public Task(SampleService sampleService, String env) {this.sampleService= sampleService;this.env = env;}@Overridepublic void run() {// do something}}

b 编写监听类
c 用ScheduledExecutorService调用任务

package com.xxx.awk.listener;import com.xxx.awk.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** @author: youxingyang* @date: 2018/8/30 9:09*/
public class ContextListener implements ServletContextListener {private ScheduledExecutorService pool = null;public ContextListener() {}/*** 初始化定时器* web 程序运行时候自动加载*/public void contextInitialized(ServletContextEvent arg0) {try {//获取serviceWebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext());SampleService sampleService = (SampleService) webApplicationContext.getBean("sampleService");// 设置一个定时器pool = Executors.newScheduledThreadPool(1);arg0.getServletContext().log("定时器已启动");// 根据工程运行环境不同调取不同配置文件String env = arg0.getServletContext().getInitParameter("spring.profiles.active");if (StringUtils.isBlank(env)) {env = "development";}/*** 每2小时执行某个操作(如某个类,或方法)*/Task t2 = new Task(sampleService, env);pool.scheduleAtFixedRate(t2, 30, 3600 * 2, TimeUnit.SECONDS);} catch (Exception e) {e.printStackTrace();arg0.getServletContext().log("任务调度表遇到异常: " + e.getMessage());}arg0.getServletContext().log("已经添加任务调度表");}/*** 销毁*/public void contextDestroyed(ServletContextEvent arg0) {pool.shutdown();arg0.getServletContext().log("定时器销毁");}
}

web.xml添加监听

<listener><listener-class>com.xxx.awk.listener.ContextListener</listener-class></listener>

小结

当工程运行起来时,定时器延时30秒后将每隔2小时运行一次。

题外话

如果工程生产环境采用了集群环境会涉及一个问题,定时器会被重复执行,可以采用分布式锁策略或者数据库乐观锁解决。

  相关解决方案