带有 ScheduledExecutorService 的 java 中的重试机制

问题描述

我正在尝试用 Java 编写一个重试机制,该机制会在 3 分钟后在失败时重试函数,并且最多重试 3 次。 我不想使用 Thread.Sleep,而是考虑使用 scheduledexecutorservice。我想弄清楚什么是它的好实现。似乎 executor.schedule() 不是 runnable 里面的 runnable。

我是这样想的:

scheduledexecutorservice executor = Executors.newScheduledThreadPool(1);
final int count = 1;
final int MAX_RETRY = 3;
Runnable runnable = () -> {
   try {
     //This function can fail and throw FunctionException
     callMyFunction();
   }
   catch (FunctionException e) {
     if (++count <= MAX_RETRY) {
        executor.schedule(runnable,30*60*1000);
     }
   }
};

executor.execute(runnable);

解决方法

我建议您使用 spring-retry 库,而不是编写自己的实现。

创建一个 RetryTemplate 实例。此处的示例代码 - https://github.com/innovationchef/batchpay/blob/master/src/main/java/com/innovationchef/service/PayApiRetryTemplate.java

然后像这样调用你的方法 -

retryTemplate.execute(arg -> callMyFunction());
,

此代码似乎有效,并解决了我遇到的问题。 我无法使用 lambda 来实现我的 Runnable 函数,因为在 lambda 中没有办法让“this”引用这一行中由 lambda 表达式创建的实例:

scheduler.schedule(this,1,TimeUnit.SECONDS);

知道如何解决这个问题吗?

完整代码如下:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
AtomicInteger counter = new AtomicInteger(1);
final int MAX_RETRY = 3;
scheduler.execute(new Runnable() {
   @Override
   public void run () {
   try {
     System.out.println("Attempt number: " + counter.get());
     functionCall();
     scheduler.shutdown();
   }
   catch (Exception e) {
      if (counter.get() < MAX_RETRY) {
            System.out.println("Attempt number: " + counter.getAndIncrement() + " failed.");
            scheduler.schedule(this,TimeUnit.SECONDS);
      }
      else {
         System.out.println("Error message: " + e.getMessage());
         scheduler.shutdown();
      }
   }
 }
 });
 }
    
 public static void functionCall() {
     throw new RuntimeException("Does not work");
 }

感谢@Turing85 的帮助和有用的评论。