定时任务+redis实现超时管理

一、使用TimerTaskch创建

1、重写TimerTask

TimerTask 的子类可以通过实现 run() 方法来定义具体的任务逻辑。当定时任务被触发时,run() 方法会在后台线程中执行。

TimerTask 主要用于在指定的时间点或时间间隔执行某个任务。

以下是 TimerTask 的一些常见用途:

  1. 执行定时任务:你可以继承 TimerTask 并实现 run() 方法来执行需要定时执行的任务,比如定期备份数据库、定时发送邮件等。

  2. 定时调度任务:你可以使用 TimerTask 配合 TimerScheduledExecutorService 来实现任务的定时调度,例如每隔一段时间执行一次任务或者在特定的时间点执行任务。

重写run方法实现定时任务内容


@Component
public class MyTask extends TimerTask implements Serializable {
    private final RequirementsDao requirementsDao;
    private PersonSendOrderVO personSendOrderVO;

    public MyTask(RequirementsDao requirementsDao) {
        this.requirementsDao = requirementsDao;
    }

    public void setPersonSendOrderVO(PersonSendOrderVO personSendOrderVO) {
        this.personSendOrderVO = personSendOrderVO;
    }

    private static final long serialVersionUID = 1L;

    @Override
    public void run() {
        requirementsDao.deleteSendOrder(personSendOrderVO.getRequirementsInfoId());
        System.out.println("定时任务执行完毕!");
    }
}

private PersonSendOrderVO personSendOrderVO;即为定时任务执行所需要参数

RequirementsDao requirementsDao;dao层代码需要利用构造函数引入,不能使用依赖注入

2、封装定时任务工具类


@Component
public class ScheduledTaskUtil {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private TaskScheduler taskScheduler;

    @Autowired
    private RequirementsDao requirementsDao;

    private final Map<Integer, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();

    public void create(PersonSendOrderVO personSendOrderVO){
        long delay = 10000; // 延迟10s开始执行
        MyTask task = new MyTask(requirementsDao);
        task.setPersonSendOrderVO(personSendOrderVO);
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.opsForValue().set("task"+personSendOrderVO.getRequirementsInfoId(), task, delay, TimeUnit.MILLISECONDS);
        // 使用TaskScheduler执行定时任务
        System.out.println("定时任务已开启");
        ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(task, Instant.now().plusMillis(delay));
        scheduledTasks.put(personSendOrderVO.getRequirementsInfoId(), scheduledFuture);
    }

    public void destroy(Integer requireId){
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        MyTask task = (MyTask) redisTemplate.opsForValue().get("task"+requireId);
        ScheduledFuture<?> scheduledFuture = scheduledTasks.get(requireId);
        if (task != null && scheduledFuture != null) {
            scheduledFuture.cancel(false);
            redisTemplate.delete("task"+requireId);
            scheduledTasks.remove(requireId);
            System.out.println("定时任务已取消");
        }
    }
}

使用redis用于保存task对象

ScheduledTaskUtil 类中,我们使用 scheduledTasks 对象来保存每个定时任务的 ScheduledFuture 对象。这样做的目的是为了在需要取消任务时,能够根据任务的唯一标识(requireId)快速找到对应的 ScheduledFuture 对象,并调用其 cancel() 方法来取消任务。

具体来说,在 create() 方法中,我们使用 taskScheduler.schedule() 方法创建定时任务,并将返回的 ScheduledFuture 对象保存到 scheduledTasks 中。

destroy() 方法中,我们根据传入的 requireIdscheduledTasks 中获取对应的 ScheduledFuture 对象,并调用其 cancel() 方法来取消任务。然后,我们再从 scheduledTasks 中移除该任务的相关内容。

通过使用 scheduledTasks 对象,我们可以有效地管理和取消定时任务。

二、使用 ScheduledExecutorService 创建

 

ScheduledExecutorService 相较于 TimerTask 配合 Timer 有以下优势:

  1. 线程安全性:ScheduledExecutorService 是线程安全的,可以在多线程环境下使用,而 TimerTaskTimer 是非线程安全的。由于 Timer 内部只有一个线程用于执行任务,如果一个任务执行时间过长,会影响其他任务的执行。

  2. 灵活性:ScheduledExecutorService 提供了更多的调度方式。除了支持延迟执行任务外,还可以按固定频率执行任务、在指定时间点执行任务等。而 TimerTask 只能支持延迟执行任务。

  3. 异常处理:ScheduledExecutorService 可以捕获任务执行过程中的异常,避免异常导致整个任务被取消。而 TimerTask 无法捕获任务执行过程中的异常,一旦出现异常,整个 Timer 将会终止。

  4. 取消任务:ScheduledExecutorService 提供了 cancel() 方法用于取消任务的执行,而 TimerTask 需要通过 cancel() 方法取消 Timer 中的全部任务。这意味着,使用 ScheduledExecutorService 可以针对单个任务进行取消,而不影响其他任务的执行。

  5. 扩展性:ScheduledExecutorServiceExecutorService 接口的子接口,可以与其他 ExecutorService 相结合使用,实现更复杂的任务调度逻辑。而 TimerTaskTimer 用法相对简单,不易扩展

@Component
public class Test {
    @Autowired
    private RequirementsDao requirementsDao;
    private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
    private final ConcurrentHashMap<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();

    public void create(PersonSendOrderVO personSendOrderVO, long delay) {
        String requireId = personSendOrderVO.getRequirementsInfoId().toString();
//        Runnable task = () -> requirementsDao.deleteSendOrder(personSendOrderVO.getRequirementsInfoId());
        Runnable task = () -> System.out.println("定时任务已执行");
        ScheduledFuture<?> scheduledFuture = scheduledExecutorService.schedule(task, delay, TimeUnit.MILLISECONDS);
        scheduledTasks.put(requireId, scheduledFuture);
        System.out.println("定时任务已创建,requirementsInfoId:" + requireId);
    }
    public void destroy(Integer requirementsInfoId) {
        String requireId = requirementsInfoId.toString();
        ScheduledFuture<?> scheduledFuture = scheduledTasks.remove(requireId);
        if (scheduledFuture != null) {
            scheduledFuture.cancel(true);
            System.out.println("定时任务已取消,requirementsInfoId:" + requireId);
        }
    }
}

 

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值