Try-catch是用来帮助异常处理的。这意味着它将在某种程度上帮助我们的系统变得更加健壮:尝试从意外事件中恢复。

我们怀疑在执行和指令(发送消息)时可能会发生一些事情,因此它被包含在try中。如果发生了几乎意想不到的事情,我们可以做些什么:我们编写捕获。我不认为我们调用只是为了记录异常。我认为catch块是为了给我们从错误中恢复的机会。

现在,假设我们从错误中恢复,因为我们可以修复错误。如果能再试一次,那就太好了:

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

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

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


当前回答

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

 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
}

其他回答

这些答案基本上都是一样的。我的也是,但我喜欢这种形式

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);
}

使用带有本地状态标志的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次,如果不成功,直到那时将退出,如果它成功之前。

将@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);
            }
        }
    }
}

通常,最好的设计取决于特定的环境。通常我会这样写:

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

你可以从jcabi-aspect(我是一名开发人员)使用AOP和Java注释:

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

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