我有一个场景,我必须轮询远程服务器检查任务是否已完成.一旦有,我会进行不同的调用以检索结果.
我原本认为我应该使用带有scheduleWithFixedDelay的SingleThreadScheduledExecutor进行轮询:
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,所以我不明白将来什么时候会完成.调用future.get()甚至意味着什么?我在等什么结果?
我第一次检测到远程任务已完成时,我想执行一个不同的远程调用并将其结果设置为将来的值.我想我可以使用CompletableFuture,我会转发到我的poll方法,然后将它转发到我的retrieveTask方法,最终完成它:
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))我想,但是当我的CompletableFuture取消/完成时,我将如何正确关闭执行程序并取消它返回的未来?感觉应该以一种完全不同的方式实施民意调查.
解决方法:
我认为CompletableFutures是一个很好的方法:
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private void run() {
final Object jobResult = pollForCompletion("jobId1")
.thenRun(jobId -> remoteServer.getJobResult(jobId))
.get();
}
private CompletableFuture<String> pollForCompletion(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;
}