如何使用 java 8 功能简化重试代码块

2022-09-04 23:50:43

在我的代码中,我有一个部分尝试连接到某个外部接口,如果它失败了,那么它将重试固定的次数。代码有效,但有些丑陋。我想知道这是否可以使用一些花哨的Java8功能以更优雅的方式完成?

int count = 0;
final int maxRetries = 3;
while ( count < maxRetries )
{
   try
   {
     // Some Code
     // break out of loop on success
   }
   catch ( final ExecutionException e )
   {
      LOG.debug( "retrying..." );
      if ( ++count >= maxRetries )
      {
         LOG.debug( "do something else...");
         //do something else
      }
   }
}

答案 1

您可以做的是分离出重试逻辑。您需要一些辅助脚手架:

interface ThrowingTask {
    void run() throws ExecutionException;
}

现在,你写道:

boolean runWithRetries(int maxRetries, ThrowingTask t) { 
    int count = 0;
    while (count < maxRetries) {
        try {
            t.run();
            return true;
        }
        catch (ExecutionException e) {
            if (++count >= maxRetries)
                return false;
        }
    }
}

现在,您可以使用重试来运行操作,而不必将任务逻辑与重试逻辑混为一谈:

runWithRetries(MAX_RETRIES, () -> { /* do stuff */ });

您可以调整它,因为您希望接受重试时调用的lambda,返回重试计数等。但是游戏是编写一些方法,比如捕获控制流,但抽象出需要完成的行为 - 所以你只需要编写一次重试循环,然后在需要的地方填写你想要的实际行为。runWithRetries


答案 2

使用故障安全

RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(ExecutionException.class)
  .withMaxRetries(3);

Failsafe.with(retryPolicy)
  .onRetry(r -> LOG.debug("retrying..."))
  .withFallback(e -> LOG.debug("do something else..."))
  .run(() -> someCode());

它就像您的用例一样简单和富有表现力。


推荐