And*_*ias 185 java exception-handling exception try-catch
Try-catch旨在帮助进行异常处理.这意味着它将以某种方式帮助我们的系统更加健壮:尝试从意外事件中恢复.
我们怀疑在执行和指令(发送消息)时可能会发生某些事情,因此它会被包含在try中.如果发生几乎意外的事情,我们可以做点什么:我们写下了捕获.我认为我们没有打电话来记录异常.我认为catch块意味着让我们有机会从错误中恢复.
现在,假设我们可以从错误中恢复,因为我们可以修复错误.重做是非常好的:
try{ some_instruction(); }
catch (NearlyUnexpectedException e){
fix_the_problem();
retry;
}
Run Code Online (Sandbox Code Playgroud)
这将很快落入永恒循环,但是假设fix_the_problem返回true,那么我们重试.鉴于Java中没有这样的东西,你将如何解决这个问题?解决这个问题的最佳设计代码是什么?
这就像一个哲学问题,因为我已经知道我所要求的并不是Java直接支持的.
Roh*_*ain 280
你需要将你的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;
}
}
Run Code Online (Sandbox Code Playgroud)
我已经采取count
并maxTries
避免遇到无限循环,以防异常继续发生在你的try block
.
ach*_*ach 52
强制性的"企业家"解决方案:
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
并致电:
OperationHelper.doWithRetry(5, new Operation() {
@Override public void doIt() {
//do some stuff
}
@Override public void handleException(Exception cause) {
//recover from the Exception
}
});
Run Code Online (Sandbox Code Playgroud)
mer*_*ike 33
像往常一样,最好的设计取决于具体情况.通常,我写的东西如下:
for (int retries = 0;; retries++) {
try {
return doSomething();
} catch (SomeException e) {
if (retries < 6) {
continue;
} else {
throw e;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*exR 19
虽然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);
}
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*han 17
您通过Failsafe处理的确切方案:
RetryPolicy retryPolicy = new RetryPolicy()
.retryOn(NearlyUnexpectedException.class);
Failsafe.with(retryPolicy)
.onRetry((r, f) -> fix_the_problem())
.run(() -> some_instruction());
Run Code Online (Sandbox Code Playgroud)
很简单.
yeg*_*256 16
您可以使用jcabi-aspects的 AOP和Java注释(我是开发人员):
@RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) {
return url.openConnection().getContent();
}
Run Code Online (Sandbox Code Playgroud)
您也可以使用@Loggable
和@LogException
注释.
Spring AOP和基于注解的解决方案:
用法(@RetryOperation
是我们对该作业的自定义注释):
@RetryOperation(retryCount = 1, waitSeconds = 10)
boolean someMethod() throws Exception {
}
Run Code Online (Sandbox Code Playgroud)
我们需要两件事来完成此任务:1. 一个注释接口,2. 一个 spring 方面。这是实现这些的一种方法:
注释接口:
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RetryOperation {
int retryCount();
int waitSeconds();
}
Run Code Online (Sandbox Code Playgroud)
春季方面:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
大多数答案基本相同.我也是,但这是我喜欢的形式
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);
}
Run Code Online (Sandbox Code Playgroud)
使用while
带有本地status
标志的循环。将标志初始化为false
并true
在操作成功时将其设置为如下所示:
boolean success = false;
while(!success){
try{
some_instruction();
success = true;
} catch (NearlyUnexpectedException e){
fix_the_problem();
}
}
Run Code Online (Sandbox Code Playgroud)
这将不断重试,直到成功。
如果您只想重试特定次数,那么也可以使用计数器:
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
}
Run Code Online (Sandbox Code Playgroud)
如果不成功,这将最多尝试 10 次,然后如果成功则退出。
归档时间: |
|
查看次数: |
160186 次 |
最近记录: |