如何使用ExecutorService进行轮询直到结果到达 [英] How to use ExecutorService to poll until a result arrives

查看:541
本文介绍了如何使用ExecutorService进行轮询直到结果到达的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个场景,我必须轮询远程服务器,检查任务是否已完成。一旦它有,我会进行不同的调用以检索结果。

I have a scenario where I have to poll a remote server checking if a task has completed. Once it has, I make a different call to retrieve the result.

我原本认为我应该使用 SingleThreadScheduledExecutor 使用 scheduleWithFixedDelay 进行轮询:

I originally figured I should use a SingleThreadScheduledExecutor with scheduleWithFixedDelay for polling:

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 将完整。调用 future.get()甚至意味着什么?我等待的结果是什么?

But since I can only provide a Runnable to scheduleWithFixedDelay which can't return anything, I don't understand when the future will be complete, if ever. What does calling future.get() even mean? What result am I waiting for?

我第一次检测到远程任务已完成时,我想执行一个不同的远程调用并将其结果设置为将来。我想我可以使用CompletableFuture,我会转发到我的 poll 方法,然后将它转发到我的 retrieveTask 最终完成它的方法:

The first time I detect the remote task has completed, I want to execute a different remote call and set its result as the value of the future. I figured I could use CompletableFuture for this, that I would forward to my poll method, which would in turn forward it to my retrieveTask method that would eventually complete it:

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 取消/完成时返回的 future ?感觉轮询应该以完全不同的方式实现。

But this has a ton of issues. For one, CompletableFuture doesn't even seem to be intended for this kind of use. Instead I should be doing CompletableFuture.supplyAsync(() -> poll(jobId)) I think, but how would I then properly shutdown the executor and cancel the future it returned when my CompletableFuture is canceled/complete? It feels like polling should be implemented in some completely different way.

推荐答案

我认为CompletableFutures是一个很好的方法:

I think CompletableFutures are a fine way to do this:

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;
}

这篇关于如何使用ExecutorService进行轮询直到结果到达的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆