这是CompletableFuture
非常基本的递归,我想让系统可靠,所以每次有异常再次重启进程,我相信它有太多的问题,希望得到你的反馈
private CompletableFuture<?> recursion() {
return CompletableFuture.runAsync(() -> {
//code here
}).handleAsync((v, th) -> {
if (th != null)
return this.recursion();
else
return v;
});
}
编辑1:
int tries =5;
private CompletableFuture<?> recursion() {
return CompletableFuture.runAsync(() -> {
//code here
}).handleAsync((v, th) -> {
if (th != null && tries-- > 0){
Thread.sleep(1000);
return this.recursion();
}else
return v;
});
}
Edit2:清理代码作为返回CompletableFuture
AtomicInteger tries =5;
private void recursion() {
CompletableFuture.runAsync(() -> {
//code here
}).whenCompleteAsync((v, th) -> {
if (th != null && ( tries.getAndDecrement() > 0 ) ){
Thread.sleep(1000);
this.recursion();
});
}
请给我你的反馈,我在争论,但真的很感激。
一般来说,当异常发生时,简单地重试操作,而不处理异常来分析失败的原因,离创建可靠的系统还很远。
然而,如果您想实现重试,您的代码将无法正确执行此操作。
您的代码恰好被编译器接受,因为您使用的操作不产生值并返回CompletableFuture
传递给handleAsync
的双函数应该提供结果值,但您调用的this. postsion()
会产生CompletableFuture
如果您将返回类型声明为CompletableFuture
通常,您不应该使用递归进行重复。没有理由这样做。让我们用一个返回值的动作来演示逻辑:
CompletableFuture<String> performAsyncAction() {
Supplier<String> action=() -> {
if(Math.random()>0.2)
throw new IllegalStateException("simulated failure");
return "value implying success";
};
int retries=5;
return CompletableFuture.supplyAsync(() -> {
try { return action.get(); }
catch(Throwable t) {
for(int i=0; i<retries; i++) try {
Thread.sleep(1000);
return action.get();
} catch(Throwable next) { t.addSuppressed(next); }
throw t;
}
});
}
很容易适应使用Runnable
、runAsync
和CompletableFuture
更新:如果您只想安排重试而不向发起者提供反馈,您可以通过等待延迟过去来实现它而不阻塞线程:
static ScheduledExecutorService e = Executors.newSingleThreadScheduledExecutor();
static void performAsyncAction(Runnable r, int tries, long delay, TimeUnit u) {
if(tries>0)
e.execute(()-> { try { r.run(); } catch(Throwable t) {
e.schedule(()->performAsyncAction(r, tries-1, delay, u), delay, u);
}});
}
这使用递归,因为它解决了lambda表达式。如果您使用内部类,这同样可以在没有递归的情况下工作:
static ScheduledExecutorService e = Executors.newSingleThreadScheduledExecutor();
static void performAsyncAction(Runnable r, int tries, long delay, TimeUnit u) {
if(tries>0)
e.execute(new Runnable() {
int left = tries;
public void run() {
try { r.run(); } catch(Throwable t) {
if(--left > 0) e.schedule(this, delay, u);
}
}
});
}