Bas*_*hdy 5 java recursion functional-programming future java-8
这是非常基本的递归CompletableFuture,我想建立可靠的系统,所以每次遇到异常都要重新启动进程,我相信它有太多问题,并且希望得到您的反馈
private CompletableFuture<?> recursion() {
return CompletableFuture.runAsync(() -> {
//code here
}).handleAsync((v, th) -> {
if (th != null)
return this.recursion();
else
return v;
});
}
Run Code Online (Sandbox Code Playgroud)
编辑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;
});
}
Run Code Online (Sandbox Code Playgroud)
Edit2:清理代码,因为返回 CompletableFuture<?>不需要,所以void考虑到 @Holger 注释并使用 AtomicInteger 进行尝试,将其挂起以返回
AtomicInteger tries =5;
private void recursion() {
CompletableFuture.runAsync(() -> {
//code here
}).whenCompleteAsync((v, th) -> {
if (th != null && ( tries.getAndDecrement() > 0 ) ){
Thread.sleep(1000);
this.recursion();
});
}
Run Code Online (Sandbox Code Playgroud)
请向我发送您的反馈,我正在争论,但真的很感激。
一般来说,仅仅在发生异常时重试操作,而不处理异常并分析失败的原因,距离创建可靠的系统还很远。
\n\n然而,如果您想实现重试,您的代码将无法正确执行此操作。
\n\n您的代码恰好被编译器接受,因为您使用的操作不会产生值并返回CompletableFuture<?>. 这隐藏了代码的问题:
传递给的双函数handleAsync应该提供结果值,但您正在调用this.recursion()它会产生一个CompletableFuture<?>. 编译器不介意在非例外情况下v返回,因为Void和CompletableFuture<?>具有共同的超类型 ,Object因此整个方法实际上返回CompletableFuture<Object>与返回类型 兼容的a CompletableFuture<?>。
如果您将返回类型声明为CompletableFuture<Void>,则逻辑错误会立即被识别:在特殊情况下,您正在启动另一个异步操作,但由于您没有检查它\xe2\x80\x99s 结果,而只是返回一个CompletableFuture<?>,然后将其视为Object,调用者永远不会注意到重试(或后续重试)是否失败。调用者将始终收到一个CompletableFuture<?>报告成功的消息,其中包含(Void)null或CompletableFuture<?>作为结果值。
一般来说,您不应该\xe2\x80\x99 使用递归进行重复。没有理由这样做。让\xe2\x80\x99s 通过返回值的操作来演示逻辑:
\n\nCompletableFuture<String> performAsyncAction() {\n Supplier<String> action=() -> {\n if(Math.random()>0.2)\n throw new IllegalStateException("simulated failure");\n return "value implying success";\n };\n int retries=5;\n return CompletableFuture.supplyAsync(() -> {\n try { return action.get(); }\n catch(Throwable t) {\n for(int i=0; i<retries; i++) try {\n Thread.sleep(1000);\n return action.get();\n } catch(Throwable next) { t.addSuppressed(next); }\n throw t;\n }\n });\n}\nRun Code Online (Sandbox Code Playgroud)\n\n它\xe2\x80\x99s很容易适应使用Runnable,runAsync和CompletableFuture<Void>。
更新:如果您只想安排重试而不向发起者提供反馈,您可以通过等待延迟过去来实现它而不阻塞线程:
\n\nstatic ScheduledExecutorService e = Executors.newSingleThreadScheduledExecutor();\n\nstatic void performAsyncAction(Runnable r, int tries, long delay, TimeUnit u) {\n if(tries>0)\n e.execute(()-> { try { r.run(); } catch(Throwable t) {\n e.schedule(()->performAsyncAction(r, tries-1, delay, u), delay, u);\n }});\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这使用了递归,因为它决定了 lambda 表达式。如果您使用内部类,则无需递归即可实现相同的效果:
\n\nstatic ScheduledExecutorService e = Executors.newSingleThreadScheduledExecutor();\n\nstatic void performAsyncAction(Runnable r, int tries, long delay, TimeUnit u) {\n if(tries>0)\n e.execute(new Runnable() {\n int left = tries;\n public void run() {\n try { r.run(); } catch(Throwable t) {\n if(--left > 0) e.schedule(this, delay, u);\n }\n }\n });\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4377 次 |
| 最近记录: |