ExecutorService を使用して結果が到着するまでポーリングする方法 質問する

ExecutorService を使用して結果が到着するまでポーリングする方法 質問する

タスクが完了したかどうかを確認するためにリモート サーバーをポーリングする必要があるシナリオがあります。タスクが完了したら、別の呼び出しを行って結果を取得します。

当初は、ポーリングにはSingleThreadScheduledExecutorwith を使用する必要があると考えていました。scheduleWithFixedDelay

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture future = executor.scheduleWithFixedDelay(() -> poll(jobId), 0, 10, TimeUnit.SECONDS);

public void poll(String jobId) {
   boolean jobDone = remoteServer.isJobDone(jobId);
   if (jobDone) {
       retrieveJobResult(jobId);
   }
}

Runnableしかし、何も返さないを提供することしかできないため、 がいつ完了するのか、あるいは完了するかどうかがscheduleWithFixedDelayわかりません。 呼び出しとは一体何を意味するのでしょうか? どのような結果を待っているのでしょうか?futurefuture.get()

リモート タスクが完了したことを初めて検出したときに、別のリモート呼び出しを実行し、その結果を の値として設定したいと思います。これには、 を自分のメソッドに転送し、そのメソッドがそれを自分のメソッドに転送して、最終的にタスクを完了させるという方法をfuture使用できることCompletableFutureを検討しました。pollretrieveTask

CompletableFuture<Object> result = new CompletableFuture<Object>();
ScheduledFuture future = executor.scheduleWithFixedDelay(() -> poll(jobId, result), 0, 10, TimeUnit.SECONDS);

public void poll(String jobId, CompletableFuture<Object> result) {
   boolean jobDone = remoteServer.isJobDone(jobId);
   if (jobDone) {
       retrieveJobResult(jobId, result);
   }
}

public void retrieveJobResult(String jobId, CompletableFuture<Object> result) {
    Object remoteResult = remoteServer.getJobResult(jobId);
    result.complete(remoteResult);
}

しかし、これには多くの問題があります。まず、CompletableFutureこの種の使用を意図していないようです。代わりに、がキャンセル/完了したときにCompletableFuture.supplyAsync(() -> poll(jobId))を適切にシャットダウンして、返された をexecutorキャンセルするにはどうすればいいと思いますか? ポーリングは、まったく異なる方法で実装する必要があるように感じます。futureCompletableFuture

ベストアンサー1

CompletableFutures はこれを行うための優れた方法だと思います。

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

private void run() {
    final Object jobResult = pollForCompletion("jobId1")
            .thenApply(jobId -> remoteServer.getJobResult(jobId))
            .get();

}

private CompletableFuture<String> pollForCompletion(final String jobId) {
    CompletableFuture<String> completionFuture = new CompletableFuture<>();
    final ScheduledFuture<Void> checkFuture = executor.scheduleAtFixedRate(() -> {
        if (remoteServer.isJobDone(jobId)) {
            completionFuture.complete(jobId);
        }
    }, 0, 10, TimeUnit.SECONDS);
    completionFuture.whenComplete((result, thrown) -> {
        checkFuture.cancel(true);
    });
    return completionFuture;
}

おすすめ記事