ScheduledExecutorService#scheduleAtFixedRate
を使用して、リモートサーバー上でタスクをスケジュールし、完了をポーリングする次のコードがあります(my previous questionの結果)。タスクが完了すると、結果がダウンロードされます。 呼び出し元にFuture
を返信して、ブロックする時期と時間を決定し、タスクをキャンセルするオプションを与えることができます。CompletableFuture#thenApplyが使用されている場合は、whenCompleteは呼び出されません。
クライアントがを返した場合、download
メソッドで返された場合、whenComplete
ブロックは実行されません。 thenApply
が削除された場合それは私が何かを誤解していることは明らかですFuture
構成...私は何を変更する必要がありますか?同じノートで
public Future<Object> download(Something something) {
String jobId = schedule(something);
CompletableFuture<String> job = pollForCompletion(jobId);
return job.thenApply(this::downloadResult);
}
private CompletableFuture<String> pollForCompletion(String jobId) {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
CompletableFuture<String> completionFuture = new CompletableFuture<>();
ScheduledFuture<?> checkFuture = executor.scheduleAtFixedRate(() -> {
if (pollRemoteServer(jobId).equals("COMPLETE")) {
completionFuture.complete(jobId);
}
}, 0, 10, TimeUnit.SECONDS);
completionFuture
.whenComplete((result, thrown) -> {
System.out.println("XXXXXXXXXXX"); //Never happens unless thenApply is removed
checkFuture.cancel(true);
executor.shutdown();
});
return completionFuture;
}
、私がしなければ:代わりに
completionFuture.whenComplete(...);
return completionFuture;
whenComplete
の
return completionFuture.whenComplete(...)
も実行されません。これは私にとって非常に直感的ではないようです。論理的には、がwhenComplete
で返されてはいけません。
EDIT:
は私が明示的にキャンセルをバック伝播するために自分のコードを変更しました。それは忌まわしいと読めないのですが、それは動作し、私はより良い方法を見つけることができませんでした:次のように
public Future<Object> download(Something something) throws ChartDataGenException, Exception {
String jobId = schedule(report);
CompletableFuture<String> job = pollForCompletion(jobId);
CompletableFuture<Object> resulting = job.thenApply(this::download);
resulting.whenComplete((result, thrown) -> {
if (resulting.isCancelled()) { //the check is not necessary, but communicates the intent better
job.cancel(true);
}
});
return resulting;
}
'whenComplete'ブロックに入ることさえありません。私はブレークポイントと 'System.out.print'を内部に入れ、ブレークポイントにもヒットしたり、行を印刷したりしません。両方とも 'thenApply'ビットを削除すると起こります。 – kaqqao
私の理解によると、それはあなたが報告したものの逆でなければなりません。 'completionFuture.whenComplete()'は純関数であり、 'completionFuture'自体が動作する方法で何も変更すべきではありません。 'whenComplete'の結果を返さないと、到達不能になり、GCの対象となります。 –
絶対に同意します。しかし、これは私が見ているものです... 'whenComplete'の結果を返し、直ちに' cancel'すると、私はコンソールにXXXXXを取得しません。一方、元の 'completionFuture'と' cancel'_that_を返すとします。 – kaqqao