你如何实现重试捕获?

Posted

技术标签:

【中文标题】你如何实现重试捕获?【英文标题】:How do you implement a re-try-catch? 【发布时间】:2012-10-25 18:04:25 【问题描述】:

Try-catch 旨在帮助处理异常。这意味着它将以某种方式帮助我们的系统更加健壮:尝试从意外事件中恢复。

我们怀疑在执行和指令(发送消息)时可能会发生某些事情,所以它被包含在 try 中。如果发生了几乎出乎意料的事情,我们可以做一些事情:我们编写 catch。我不认为我们打电话只是为了记录异常。我认为 catch 块是为了让我们有机会从错误中恢复。

现在,假设我们从错误中恢复,因为我们可以修复错误。重试可能会非常好:

try some_instruction(); 
catch (NearlyUnexpectedException e)
   fix_the_problem();
   retry;

这将很快陷入永恒循环,但假设 fix_the_problem 返回 true,然后我们重试。鉴于Java中没有这样的东西,你将如何解决这个问题?解决这个问题的最佳设计代码是什么?

这就像一个哲学问题,因为我已经知道我所要求的不是 Java 直接支持的。

【问题讨论】:

这是什么异常? 我喜欢你的例外的名字。 ;) 事实上,您可以从中恢复的异常并不多。我承认我最初的动机并不是一个真正的例外,而是避免这种情况几乎永远不会发生的方法:我尝试从java.util.Queueremove(),当队列为空时,这会触发和InvalidElementException。我没有询问它是否为空,而是将动作包围在一个 try-catch 中(即使在前一个 if 的情况下,它在并发下也成为强制性的)。在这种情况下,在catch 块中,我会要求用更多元素重新填充队列,然后重试。瞧。 我可以看到执行此操作的通常方法是访问数据库,如果连接失败重新连接,如果失败则抛出重大异常,否则重试调用。如前所述,我们可以在循环中执行此操作,并在底部检查 if(error0) 然后返回,否则 break; 【参考方案1】:

您需要将try-catch 包含在while 循环中,如下所示:-

int count = 0;
int maxTries = 3;
while(true) 
    try 
        // Some Code
        // break out of loop, or return, on success
     catch (SomeException e) 
        // handle exception
        if (++count == maxTries) throw e;
    

我采取了countmaxTries 来避免陷入无限循环,以防您的try block 中继续发生异常。

【讨论】:

我起初是这样想的,没有 maxTries。感谢您的回答! @AndresFarias .. 是的,这个答案中最重要的一点是包含maxTries。否则,如果用户不断输入错误,它将运行到infinite loop,因此不会退出。不过不客气。 :) 谢谢你 - 它让我不必编写一些非常粗糙的代码! 是否可以在此处的 catch 中添加 Thread.sleep() 函数。因为在某些情况下,例如在 Selenium 库中等待页面响应变得至关重要。谢谢。 效果很好!对于初学者:如果你得到积极的无限循环,请检查你是否添加了“break;”在“try”块的末尾。【参考方案2】:

强制性“企业”解决方案:

public abstract class Operation 
    abstract public void doIt();
    public void handleException(Exception cause) 
        //default impl: do nothing, log the exception, etc.
    


public class OperationHelper 
    public static void doWithRetry(int maxAttempts, Operation operation) 
        for (int count = 0; count < maxAttempts; count++) 
            try 
                operation.doIt();
                count = maxAttempts; //don't retry
             catch (Exception e) 
                operation.handleException(e);
            
        
    

然后调用:

OperationHelper.doWithRetry(5, new Operation() 
    @Override public void doIt() 
        //do some stuff
    
    @Override public void handleException(Exception cause) 
        //recover from the Exception
    
);

【讨论】:

如果最后一次重试失败,您应该重新抛出异常,如给出的其他答案中所做的那样。【参考方案3】:

像往常一样,最佳设计取决于特定情况。不过,通常我会写如下内容:

for (int retries = 0;; retries++) 
    try 
        return doSomething();
     catch (SomeException e) 
        if (retries < 6) 
            continue;
         else 
            throw e;
        
    

【讨论】:

等等,为什么在 for 循环声明中没有条件,例如:for(int retries = 0; retries 因为我只想在最后一次尝试中抛出,因此 catch 块需要那个条件,使得 for 中的条件变得多余。 我不认为那里需要continue。你可以简单地翻转if条件。【参考方案4】:

您通过Failsafe处理的确切场景:

RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(NearlyUnexpectedException.class);

Failsafe.with(retryPolicy)
  .onRetry((r, f) -> fix_the_problem())
  .run(() -> some_instruction());

很简单。

【讨论】:

非常好的图书馆。 对于那些想知道的人,您将在您的 gradle 依赖项中需要它 - 编译 'net.jodah:failsafe:1.1.0'【参考方案5】:

虽然try/catch 变成while 是众所周知的好策略,但我想建议你递归调用:

void retry(int i, int limit) 
    try 

     catch (SomeException e) 
        // handle exception
        if (i >= limit) 
            throw e;  // variant: wrap the exception, e.g. throw new RuntimeException(e);
        
        retry(i++, limit);
    

【讨论】:

对于这个用例,递归比循环有什么好处? 这个堆栈跟踪可能看起来有点奇怪,因为它不会有 limit 递归方法的计数吗?与循环版本相反,它将抛出“原始”级别...... 在纸上看起来确实很优雅,但我不确定递归是否是正确的方法。 我也不明白这里为什么要递归。无论如何,我认为可以简化为:void retry(int times) (...) if (times==0) throw w; retry(times--); 使用递归代替单纯的迭代是不好的做法。当您想要推送和弹出一些数据时使用递归。【参考方案6】:

您可以使用来自jcabi-aspects(我是开发人员)的 AOP 和 Java 注释:

@RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) 
  return url.openConnection().getContent();

您还可以使用@Loggable@LogException 注释。

【讨论】:

哇!听起来很花哨! :) 应该是最佳答案。 有没有办法在尝试失败时“修复”错误(做一些可能修复下一次尝试的采用)?见问题:fix_the_problem(); 在 catch 块中 鉴于未解决的问题数量和确认的错误未得到修复的时间,我不会依赖这个库。【参考方案7】:

这些答案中的大多数基本上是相同的。我的也是,不过这是我喜欢的形式

boolean completed = false;
Throwable lastException = null;
for (int tryCount=0; tryCount < config.MAX_SOME_OPERATION_RETRIES; tryCount++)

    try 
        completed = some_operation();
        break;
    
    catch (UnlikelyException e) 
        lastException = e;
        fix_the_problem();
    

if (!completed) 
    reportError(lastException);

【讨论】:

一个缺点是您在最后一次尝试后还会调用fix_the_problem。这可能是一项昂贵的操作,并且可能会浪费一些时间。 @JoachimSauer 是的。你可以if (tryCount &lt; max) fix()——但这是一般方法的格式;细节将取决于具体情况。还有一个基于番石榴的Retryer 我一直在看。【参考方案8】:

使用带有本地 status 标志的 while 循环。将标志初始化为false,并在操作成功时将其设置为true,例如下面:

  boolean success  = false;
  while(!success)
     try 
         some_instruction(); 
         success = true;
      catch (NearlyUnexpectedException e)
       fix_the_problem();
     
  

这将继续重试直到成功。

如果您只想重试一定次数,那么也可以使用计数器:

  boolean success  = false;
  int count = 0, MAX_TRIES = 10;
  while(!success && count++ < MAX_TRIES)
     try 
         some_instruction(); 
         success = true;
      catch (NearlyUnexpectedException e)
       fix_the_problem();
     
  
  if(!success)
    //It wasn't successful after 10 retries
  

如果在此之前不成功,这将尝试最多 10 次,如果之前成功则将退出。

【讨论】:

与其在 while 中检查 !success,不如在成功为真时退出 while。 @RohitJain:对我来说它看起来更干净。 @YogendraSingh.. 奇怪。因为您没有在catch 的任何地方修改您的success。因此,在每次运行 catch 时检查它似乎是多余的。 @RohitJain:Catch 只是更正数据。它将返回并再次运行该语句。如果成功,它将修改success。试试看。【参考方案9】:

Spring AOP 和基于注解的解决方案:

用法(@RetryOperation 是我们对作业的自定义注释):

@RetryOperation(retryCount = 1, waitSeconds = 10)
boolean someMethod() throws Exception 

我们需要两件事来完成这个:1. 一个注解接口,2. 一个 spring 方面。这是实现这些的一种方法:

注解接口:

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RetryOperation 
    int retryCount();
    int waitSeconds();

春季方面:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Aspect @Component 
public class RetryAspect 

    private static final Logger LOGGER = LoggerFactory.getLogger(RetryAspect.class);

    @Around(value = "@annotation(RetryOperation)")
    public Object retryOperation(ProceedingJoinPoint joinPoint) throws Throwable 

        Object response = null;
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        RetryOperation annotation = method.getAnnotation(RetryOperation.class);
        int retryCount = annotation.retryCount();
        int waitSeconds = annotation.waitSeconds();
        boolean successful = false;

        do 
            try 
                response = joinPoint.proceed();
                successful = true;
             catch (Exception ex) 
                LOGGER.info("Operation failed, retries remaining: ", retryCount);
                retryCount--;
                if (retryCount < 0) 
                    throw ex;
                
                if (waitSeconds > 0) 
                    LOGGER.info("Waiting for  second(s) before next retry", waitSeconds);
                    Thread.sleep(waitSeconds * 1000l);
                
            
         while (!successful);

        return response;
    

【讨论】:

【参考方案10】:

这是一个老问题,但解决方案仍然相关。这是我在 Java 8 中不使用任何第三方库的通用解决方案:

public interface RetryConsumer<T> 
    T evaluate() throws Throwable;

public interface RetryPredicate<T> 
    boolean shouldRetry(T t);

public class RetryOperation<T> 
    private RetryConsumer<T> retryConsumer;
    private int noOfRetry;
    private int delayInterval;
    private TimeUnit timeUnit;
    private RetryPredicate<T> retryPredicate;
    private List<Class<? extends Throwable>> exceptionList;

    public static class OperationBuilder<T> 
        private RetryConsumer<T> iRetryConsumer;
        private int iNoOfRetry;
        private int iDelayInterval;
        private TimeUnit iTimeUnit;
        private RetryPredicate<T> iRetryPredicate;
        private Class<? extends Throwable>[] exceptionClasses;

        private OperationBuilder() 
        

        public OperationBuilder<T> retryConsumer(final RetryConsumer<T> retryConsumer) 
            this.iRetryConsumer = retryConsumer;
            return this;
        

        public OperationBuilder<T> noOfRetry(final int noOfRetry) 
            this.iNoOfRetry = noOfRetry;
            return this;
        

        public OperationBuilder<T> delayInterval(final int delayInterval, final TimeUnit timeUnit) 
            this.iDelayInterval = delayInterval;
            this.iTimeUnit = timeUnit;
            return this;
        

        public OperationBuilder<T> retryPredicate(final RetryPredicate<T> retryPredicate) 
            this.iRetryPredicate = retryPredicate;
            return this;
        

        @SafeVarargs
        public final OperationBuilder<T> retryOn(final Class<? extends Throwable>... exceptionClasses) 
            this.exceptionClasses = exceptionClasses;
            return this;
        

        public RetryOperation<T> build() 
            if (Objects.isNull(iRetryConsumer)) 
                throw new RuntimeException("'#retryConsumer:RetryConsumer<T>' not set");
            

            List<Class<? extends Throwable>> exceptionList = new ArrayList<>();
            if (Objects.nonNull(exceptionClasses) && exceptionClasses.length > 0) 
                exceptionList = Arrays.asList(exceptionClasses);
            
            iNoOfRetry = iNoOfRetry == 0 ? 1 : 0;
            iTimeUnit = Objects.isNull(iTimeUnit) ? TimeUnit.MILLISECONDS : iTimeUnit;
            return new RetryOperation<>(iRetryConsumer, iNoOfRetry, iDelayInterval, iTimeUnit, iRetryPredicate, exceptionList);
        
    

    public static <T> OperationBuilder<T> newBuilder() 
        return new OperationBuilder<>();
    

    private RetryOperation(RetryConsumer<T> retryConsumer, int noOfRetry, int delayInterval, TimeUnit timeUnit,
                           RetryPredicate<T> retryPredicate, List<Class<? extends Throwable>> exceptionList) 
        this.retryConsumer = retryConsumer;
        this.noOfRetry = noOfRetry;
        this.delayInterval = delayInterval;
        this.timeUnit = timeUnit;
        this.retryPredicate = retryPredicate;
        this.exceptionList = exceptionList;
    

    public T retry() throws Throwable 
        T result = null;
        int retries = 0;
        while (retries < noOfRetry) 
            try 
                result = retryConsumer.evaluate();
                if (Objects.nonNull(retryPredicate)) 
                    boolean shouldItRetry = retryPredicate.shouldRetry(result);
                    if (shouldItRetry) 
                        retries = increaseRetryCountAndSleep(retries);
                     else 
                        return result;
                    
                 else 
                    // no retry condition defined, no exception thrown. This is the desired result.
                    return result;
                
             catch (Throwable e) 
                retries = handleException(retries, e);
            
        
        return result;
    

    private int handleException(int retries, Throwable e) throws Throwable 
        if (exceptionList.contains(e.getClass()) || (exceptionList.isEmpty())) 
            // exception is excepted, continue retry.
            retries = increaseRetryCountAndSleep(retries);
            if (retries == noOfRetry) 
                // evaluation is throwing exception, no more retry left. Throw it.
                throw e;
            
         else 
            // unexpected exception, no retry required. Throw it.
            throw e;
        
        return retries;
    

    private int increaseRetryCountAndSleep(int retries) 
        retries++;
        if (retries < noOfRetry && delayInterval > 0) 
            try 
                timeUnit.sleep(delayInterval);
             catch (InterruptedException ignore) 
                Thread.currentThread().interrupt();
            
        
        return retries;
    

让我们有一个像这样的测试用例:

@Test
public void withPredicateAndException() 
    AtomicInteger integer = new AtomicInteger();
    try 
        Integer result = RetryOperation.<Integer>newBuilder()
                .retryConsumer(() -> 
                    int i = integer.incrementAndGet();
                    if (i % 2 == 1) 
                        throw new NumberFormatException("Very odd exception");
                     else 
                        return i;
                    
                )
                .noOfRetry(10)
                .delayInterval(10, TimeUnit.MILLISECONDS)
                .retryPredicate(value -> value <= 6)
                .retryOn(NumberFormatException.class, EOFException.class)
                .build()
                .retry();
        Assert.assertEquals(8, result.intValue());
     catch (Throwable throwable) 
        Assert.fail();
    

【讨论】:

好主意,一个建设者!【参考方案11】:

解决此问题的一种简单方法是将 try/catch 包装在 while 循环中并保持计数。这样,您可以通过检查其他变量的计数来防止无限循环,同时维护您的失败日志。这不是最精致的解决方案,但它会起作用。

【讨论】:

【参考方案12】:

如果有用,可以考虑更多选项,所有选项都放在一起(停止文件而不是重试、睡眠、继续更大的循环)都可能有用。

 bigLoop:
 while(!stopFileExists()) 
    try 
      // do work
      break;
    
    catch (ExpectedExceptionType e) 

       // could sleep in here, too.

       // another option would be to "restart" some bigger loop, like
       continue bigLoop;
    
    // ... more work

【讨论】:

投反对票的请留下 cmets 原因,谢谢! 这完全是无知投反对票并且没有给出理由。 在那里睡觉并不明显,因为while循环不会等待【参考方案13】:

如果不是所有异常都需要重试,那么只有一些。如果必须至少尝试一次,这里有一种替代实用方法:

void runWithRetry(Runnable runnable, Class<Exception> exClass, int maxRetries) 
        Exception err = null;
        do 
            maxRetries--;
            try 
                runnable.run();
                err = null;
             catch (Exception e) 
                if(exClass.isAssignableFrom(e.getClass()))
                    err = e;
                else 
                    throw e;
                
            
         while (err != null && maxRetries > 0);

        if (err != null) 
            throw err;
        
    

用法:

    runWithRetry(() -> 
       // do something
    , TimeoutException.class, 5)

【讨论】:

【参考方案14】:

Try-Catch 所做的只是让你的程序优雅地失败。在 catch 语句中,您通常会尝试记录错误,并在需要时回滚更改。

bool finished = false;

while(finished == false)

    try
    
        //your code here
        finished = true
    
    catch(exception ex)
    
        log.error("there was an error, ex");
    

【讨论】:

你的意思是与(!finished)相对吗? @RohitJain 它看起来太像while(finished)。我更喜欢使用更详细的版本。 while(!finished) 到底怎么看起来像while (finished)?? @Rohit 因为只有一个字符不同。它们都被编译成同一个东西。在 C# 中,我使用字符串扩展方法 IsPopulated(),它只返回 !IsNullOrEmpty(),以确保所有开发人员都能理解我的意图。【参考方案15】:

使用do-while来设计重试块。

boolean successful = false;
int maxTries = 3;
do
  try 
    something();
    success = true;
   catch(Me ifUCan) 
    maxTries--;
  
 while (!successful || maxTries > 0)

【讨论】:

如果不成功,代码应该抛出原始异常【参考方案16】:

这里是 Java 8+ 的可重用且更通用的方法,不需要外部库:

public interface IUnreliable<T extends Exception>

    void tryRun ( ) throws T;


public static <T extends Exception> void retry (int retryCount, IUnreliable<T> runnable) throws T 
    for (int retries = 0;; retries++) 
        try 
            runnable.tryRun();
            return;
         catch (Exception e) 
            if (retries < retryCount) 
                continue;
             else 
                throw e;
            
        
    

用法:

@Test
public void demo() throws IOException 
    retry(3, () -> 
        new File("/tmp/test.txt").createNewFile();
    );

【讨论】:

【参考方案17】:

您可以使用https://github.com/bnsd55/RetryCatch

例子:

RetryCatch retryCatchSyncRunnable = new RetryCatch();
        retryCatchSyncRunnable
                // For infinite retry times, just remove this row
                .retryCount(3)
                // For retrying on all exceptions, just remove this row
                .retryOn(ArithmeticException.class, IndexOutOfBoundsException.class)
                .onSuccess(() -> System.out.println("Success, There is no result because this is a runnable."))
                .onRetry((retryCount, e) -> System.out.println("Retry count: " + retryCount + ", Exception message: " + e.getMessage()))
                .onFailure(e -> System.out.println("Failure: Exception message: " + e.getMessage()))
                .run(new ExampleRunnable());

您可以传递自己的匿名函数,而不是 new ExampleRunnable()

【讨论】:

【参考方案18】:

将@ach 之前的解决方案简化为一个文件并使用函数式接口。

public class OperationHelper 

    public static void doWithRetry(int maxAttempts, Runnable operation, Consumer<Exception> handle) 
        for (int count = 0; count < maxAttempts; count++) 
            try 
                operation.run();
                count = maxAttempts; //don't retry
             catch (Exception e) 
                handle.accept(e);
            
        
    

【讨论】:

【参考方案19】:

我知道这里已经有很多类似的答案,我的答案也没有太大的不同,但我还是会发布它,因为它涉及特定的案例/问题。

在处理php 中的facebook Graph API 时,您有时会遇到错误,但立即重新尝试相同的事情会得到积极的结果(出于各种神奇的互联网原因,这些原因超出了这个问题的范围)。在这种情况下,没有必要修复任何错误,只需再试一次,因为存在某种“facebook错误”。

此代码在创建 facebook 会话后立即使用:

//try more than once because sometimes "facebook error"
$attempt = 3;
while($attempt-- > 0)

    // To validate the session:
    try 
    
        $facebook_session->validate();
        $attempt = 0;
     
    catch (Facebook\FacebookRequestException $ex)
    
        // Session not valid, Graph API returned an exception with the reason.
        if($attempt <= 0) echo $ex->getMessage(); 
     
    catch (\Exception $ex) 
    
        // Graph API returned info, but it may mismatch the current app or have expired.
        if($attempt <= 0) echo $ex->getMessage(); 
    

此外,通过将for 循环倒计时至零 ($attempt--),以后可以很容易地更改尝试次数。

【讨论】:

【参考方案20】:

以下是我的解决方案,方法非常简单!

               while (true) 
                    try 
                        /// Statement what may cause an error;
                        break;
                     catch (Exception e) 

                    
                

【讨论】:

请查看@Rohit Jain 的答案,该答案更具体,在否定情况下不是无限循环。【参考方案21】:

我不确定这是否是“专业”的方式,我也不完全确定它是否适用于所有事情。

boolean gotError = false;

do 
    try 
        // Code You're Trying
     catch ( FileNotFoundException ex ) 
        // Exception
        gotError = true;
    
 while ( gotError = true );

【讨论】:

【参考方案22】:

https://github.com/tusharmndr/retry-function-wrapper/tree/master/src/main/java/io

int MAX_RETRY = 3; 
RetryUtil.<Boolean>retry(MAX_RETRY,() -> 
    //Function to retry
    return true;
);

【讨论】:

【参考方案23】:

其余解决方案的问题是,对应函数连续尝试,中间没有时间间隔,因此堆栈溢出。

为什么不只是 trying 每秒和 ad eternum

这里使用setTimeout 和递归函数的解决方案:

(function()
  try
    Run(); //tries for the 1st time, but Run() as function is not yet defined
  
  catch(e)
    (function retry()
      setTimeout(function()
        try
          console.log("trying...");
          Run();
          console.log("success!");
        
        catch(e)
          retry(); //calls recursively
        
      , 1000); //tries every second
    ());
  
)();



//after 5 seconds, defines Run as a global function
var Run;
setTimeout(function()
  Run = function();
, 5000);

将函数Run() 替换为您希望每秒重新try 的函数或代码。

【讨论】:

【参考方案24】:

使用springs@Retryable注解试试看,下面的方法会在RuntimeException发生时重试3次

@Retryable(maxAttempts=3,value= RuntimeException.class,backoff = @Backoff(delay = 500))
public void checkSpringRetry(String str) 
    if(StringUtils.equalsIgnoreCase(str, "R")) 
        LOGGER.info("Inside retry.....!!");
        throw new RuntimeException();
    

【讨论】:

【参考方案25】:

在sn-p下面执行一些代码sn-p。如果您在执行代码 sn-p 时遇到任何错误,请休眠 M 毫秒并重试。参考link。

public void retryAndExecuteErrorProneCode(int noOfTimesToRetry, CodeSnippet codeSnippet, int sleepTimeInMillis)
  throws InterruptedException 

 int currentExecutionCount = 0;
 boolean codeExecuted = false;

 while (currentExecutionCount < noOfTimesToRetry) 
  try 
   codeSnippet.errorProneCode();
   System.out.println("Code executed successfully!!!!");
   codeExecuted = true;
   break;
   catch (Exception e) 
   // Retry after 100 milliseconds
   TimeUnit.MILLISECONDS.sleep(sleepTimeInMillis);
   System.out.println(e.getMessage());
   finally 
   currentExecutionCount++;
  
 

 if (!codeExecuted)
  throw new RuntimeException("Can't execute the code within given retries : " + noOfTimesToRetry);

【讨论】:

【参考方案26】:

这是我的解决方案,类似于其他一些可以包装函数的解决方案,但如果成功,您可以获取函数的返回值。

    /**
     * Wraps a function with retry logic allowing exceptions to be caught and retires made.
     *
     * @param function the function to retry
     * @param maxRetries maximum number of retires before failing
     * @param delay time to wait between each retry
     * @param allowedExceptionTypes exception types where if caught a retry will be performed
     * @param <V> return type of the function
     * @return the value returned by the function if successful
     * @throws Exception Either an unexpected exception from the function or a @link RuntimeException if maxRetries is exceeded
     */
    @SafeVarargs
    public static <V> V runWithRetriesAndDelay(Callable<V> function, int maxRetries, Duration delay, Class<? extends Exception>... allowedExceptionTypes) throws Exception 
        final Set<Class<? extends Exception>> exceptions = new HashSet<>(Arrays.asList(allowedExceptionTypes));
        for(int i = 1; i <= maxRetries; i++) 
            try 
                return function.call();
             catch (Exception e) 
                if(exceptions.contains(e.getClass()))
                    // An exception of an expected type
                    System.out.println("Attempt [" + i + "/" + maxRetries + "] Caught exception [" + e.getClass() + "]");
                    // Pause for the delay time
                    Thread.sleep(delay.toMillis());
                else 
                    // An unexpected exception type
                    throw e;
                
            
        
        throw new RuntimeException(maxRetries + " retries exceeded");
    

【讨论】:

【参考方案27】:

简单

int MAX = 3;

int count = 0;
while (true) 
    try 
        ...

        break;
     catch (Exception e) 
        if (count++ < MAX) 
            continue;
        

        ...
        
        break;
    

【讨论】:

【参考方案28】:

https://onlinegdb.com/a-7RsL1Gh

    public void doSomething() throws Exception
      final int MAX_TRIES = 10;
      int count = 0;
      
      while(count++ < MAX_TRIES)
         try 
            System.out.println("trying");
            causeIssue(count); // throws error/exception till count 2
            System.out.println("trying successful");
            break; // break on success
          catch (Exception e)
           System.out.println("caught, logging Exception:" + count);
          catch (Error e)
           System.out.println("caught, logging Error:" + count);
         
      
    

输出:

trying
caught, logging Error:1
trying
caught, logging Error:2
trying
trying successful

【讨论】:

以上是关于你如何实现重试捕获?的主要内容,如果未能解决你的问题,请参考以下文章

kafka 消费重试 实现

Spring Cloud Feign 重试机制-如何实现请求重试

如何利用Spring AOP实现异常重试

.NET/C#程序开发中如何更优美地实现失败任务重试的逻辑?

Scala - 使用超时重试HTTP请求

实现死锁异常的重试逻辑