How to use ExecutorService to poll before getting result

I have a scenario where I have to poll the remote server, checking if the task is completed. After that, I make another call to get the result.

I originally intended to use SingleThreadScheduledExecutor with scheduleWithFixedDelay to poll:

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

But since I can only provide Runnable to scheduleWithFixedDelay , which cannot return anything, I do not understand when the future will be completed, if ever. What does calling future.get() mean? What result am I waiting for?

When I start the remote task for the first time, I want to make another remote call and set its result as the future value. I suggested that I could use CompletableFuture to do this to forward my poll method, which in turn redirects it to my retrieveTask method, which ultimately completes 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); } 

But this has a lot of problems. For example, CompletableFuture is not even intended for such use. Instead, I had to do CompletableFuture.supplyAsync(() -> poll(jobId)) , I think, but how would I then correctly turn off the executor and cancel the future , which was returned when my CompletableFuture canceled / completed? It seems that the survey should be implemented in a completely different way.

+5
source share
2 answers

I think CompletableFutures is a good way to do this:

 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private void run() { final Object jobResult = pollForCompletion("jobId1") .thenApply(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; } 
+3
source

I think you are more concerned about some stylistic issues than any others. in java 8, CompletableFuture has 2 roles: one is the traditional future, which provides an asynchronous source for the task and status request; the other is what we usually call a promise. a promise, if you still do not know, can be considered the builder of the future and its source of completion. therefore, in this case, an intuitive promise is required, which is the exact case that you are using here. the examples you worry about are what introduces you for the first time, but not a promise.

By accepting this, it should be easier for you to get started with your real problem. I think that a promise should consist of two roles, one to notify you of the completion of your survey task, and the other to cancel the scheduled task upon completion. here should be the final solution:

 public CompletableFuture<Object> pollTask(int jobId) { CompletableFuture<Object> fut = new CompletableFuture<>(); ScheduledFuture<?> sfuture = executor.scheduleWithFixedDelay(() -> _poll(jobId, fut), 0, 10, TimeUnit.SECONDS); fut.thenAccept(ignore -> sfuture.cancel(false)); return fut; } private void _poll(int jobId, CompletableFuture<Object> fut) { // whatever polls if (isDone) { fut.complete(yourResult); } } 
+2
source

Source: https://habr.com/ru/post/1258807/


All Articles