我发现自己编写了很多看起来像
的重试循环 int triesRemaining = 3;
while (triesRemaining > 0) {
try {
<MY FUNCTION CALL>
LOGGER.info("success");
break;
} catch (Exception e) {
if (e.getCause() instanceof SocketTimeoutException) {
triesRemaining--;
LOGGER.info(e.getMessage() + " trying again. Tries Remaining: " + triesRemaining);
} else {
LOGGER.error(e.getMessage(), e);
return;
}
}
}
if (triesRemaining == 0) {
LOGGER.error("Failed over too many times");
}
我想编写一个接受Lambda的泛型函数,并且仅针对特定错误进行重试(在上述情况下为SocketTimeoutException
)。我已经看到一些接受Runnable
的函数很好,但它们似乎不允许限制特定的异常。
有什么建议吗?
答案 0 :(得分:1)
嗯,它已经完成了。它还接受您要重试的例外列表。它还提供线性/指数重试策略。 看看https://github.com/rholder/guava-retrying
来自自述文件的一个简单示例,您可以编写并使用如下的重试程序: -
Callable<Boolean> callable = new Callable<Boolean>() {
public Boolean call() throws Exception {
return true; // do something useful here
}};
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
.retryIfResult(Predicates.<Boolean>isNull())
.retryIfExceptionOfType(IOException.class)
.retryIfRuntimeException()
.withStopStrategy(StopStrategies.stopAfterAttempt(3))
.build();
try {
retryer.call(callable);
} catch (RetryException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
答案 1 :(得分:1)
查看org.springframework.retry
有一个注释@Retryable,它符合您的需要。您可以指定要重试的例外类型并配置尝试次数等...
答案 2 :(得分:0)
问题是什么让这个函数接受Runnable
参数然后在<MY FUNCTION CALL>
中运行?
public static void retry(Runnable r) {
// ...
while (triesRemaining > 0) {
try {
r.run();
LOGGER.info("success");
break;
}
// ...
}
然后调用它(如果您愿意 - 使用lambda):
retry(() -> {
connectToServer();
// todo what-ever-you-want
});
答案 3 :(得分:0)
我相信您正在寻找基于纯Java的解决方案。基于假设,我会说Java 8使用功能接口,一个带有单一抽象方法的接口。我会创建一个新的 RetryCommand 类,它有一个 run 方法,它接受一个函数。
答案 4 :(得分:0)
结帐Failsafe:
RetryPolicy retryPolicy = new RetryPolicy()
.retryOn(SocketTimeoutException.class)
.withMaxRetries(3);
Failsafe.with(retryPolicy)
.onRetry((c, f, ctx) -> log.warn("Failure #{}. Retrying.", ctx.getExecutions()))
.onFailure(e -> LOGGER.error(e.getMessage(), e))
.run(() -> myFunctionCall());