java 自定义方法重试实现

支持多种重试配置,如重试时间间隔,最大重试次数, 错误回调,间隔时间倍数等配置 

重试对象:

package com.olivia.sdk.utils.model;

import com.olivia.sdk.utils.$;
import com.olivia.sdk.utils.RunUtils;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

import java.util.Map;

@Setter
@Getter
@Slf4j
@Accessors(chain = true)
public class AsyncRunAndTry implements Runnable {

  private String key;

  @Setter(AccessLevel.NONE) // 忽略生成该字段的setter
  private Map<String, String> contextMap;
  private Runnable bizRunnable;
  private Runnable errorRunnable;
  @Setter(AccessLevel.NONE) // 忽略生成该字段的setter
  private int currentExecIndex = 1;
  private int maxLoopCount;
  private long intervalTimeMill;
  private double multipleTime = 1.0;

  @Setter(AccessLevel.NONE) // 忽略生成该字段的setter
  private Boolean finalExecResult;

  public AsyncRunAndTry() {
    contextMap = MDC.getCopyOfContextMap();
  }


  public void setIntervalTimeMill(int intervalTimeMill) {
    $.assertTrueCanIgnoreException(intervalTimeMill > 0, "任务间隔不能小于0");
    this.intervalTimeMill = intervalTimeMill;
  }


  @Override
  public void run() {

    try {
      this.currentExecIndex++;
      bizRunnable.run();
      log.error("key : {} 执行成功", key);
      this.finalExecResult = Boolean.TRUE;
    } catch (Exception e) {
      log.error("key : {} 执行异常 error:{}", key, e.getMessage());
//      log.error("key : {} 执行异常 error:{}", key, e.getMessage(), e);
      RunUtils.asyncRunAndTry(this);
    }
  }
}

实现方法:

package com.olivia.sdk.timer;

import com.olivia.sdk.utils.RunUtils;
import com.olivia.sdk.utils.model.AsyncRunAndTry;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;

@Slf4j
@Component
public class TimerUtils {

  // 静态单例 Timer 对象
  public static final Timer TIMER = new Timer();

  /**
   * 按固定延迟和周期调度任务
   *
   * @param key    任务的唯一标识
   * @param task   要执行的任务
   * @param delay  延迟执行的时间(毫秒)
   * @param period 任务执行的周期(毫秒)
   * @param logLog 是否记录日志
   */
  public static void schedule(String key, Runnable task, long delay, long period, boolean logLog) {
    TIMER.schedule(createTimerTask(key, task, logLog), delay, period);
  }

  /**
   * 按固定延迟和周期调度任务,默认记录日志
   *
   * @param key    任务的唯一标识
   * @param task   要执行的任务
   * @param delay  延迟执行的时间(毫秒)
   * @param period 任务执行的周期(毫秒)
   */
  public static void schedule(String key, Runnable task, long delay, long period) {
    schedule(key, task, delay, period, true);
  }

  /**
   * 按固定延迟调度一次性任务
   *
   * @param key    任务的唯一标识
   * @param task   要执行的任务
   * @param delay  延迟执行的时间(毫秒)
   * @param logLog 是否记录日志
   */
  public static void schedule(String key, Runnable task, long delay, boolean logLog) {
    TIMER.schedule(createTimerTask(key, task, logLog), delay);
  }

  /**
   * 按固定延迟调度一次性任务,默认记录日志
   *
   * @param key   任务的唯一标识
   * @param task  要执行的任务
   * @param delay 延迟执行的时间(毫秒)
   */
  public static void schedule(String key, Runnable task, long delay) {
    schedule(key, task, delay, true);
  }

  /**
   * 创建 TimerTask 对象
   *
   * @param key    任务的唯一标识
   * @param task   要执行的任务
   * @param logLog 是否记录日志
   * @return TimerTask 对象
   */
  private static TimerTask createTimerTask(String key, Runnable task, boolean logLog) {
    return new TimerTask() {
      @Override
      public void run() {
        try {
          task.run();
          if (logLog) {
            log.info("schedule key :{} exec:success", key);
          }
        } catch (Exception e) {
          if (logLog) {
            log.error("schedule key :{} exec:error: {}", key, e.getMessage(), e);
          }
        }
      }
    };
  }

  /**
   * 取消所有调度任务并关闭 Timer
   */
  public static void cancel() {
    TIMER.cancel();
  }

  @PreDestroy
  public static void destroy() {
    log.info("TIMER.purge() :{}", TIMER.purge());
  }

  public static void schedule(AsyncRunAndTry req) {
    if (req == null) {
      log.info("req is null return");
      return;
    }
    log.info("AsyncRunAndTry key :{} getCurrentExecIndex: {} getMaxLoopCount :{}", req.getKey(), req.getCurrentExecIndex(), req.getMaxLoopCount());
    if (req.getMaxLoopCount() < req.getCurrentExecIndex()) {
      if (Objects.nonNull(req.getErrorRunnable())) {
        RunUtils.asyncRun(req.getKey(), req.getErrorRunnable());
      }
      return;
    }

    long nextTime = Math.round(req.getCurrentExecIndex() * req.getIntervalTimeMill() * req.getMultipleTime());
    log.info("key {} 下次执行间隔 nextTime {}", req.getKey(), nextTime);
    TimerUtils.schedule(req.getKey(), req, nextTime, false);


  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值