2017-07-03 218 views
1

我想了解CompletableFuture接口的Java 8 我当前的代码是:CompletableFuture:异步调用,处理结果在当前线程后

CompletableFuture.supplyAsync(() -> wachtwoordBijwerken(gebruikersnaam, wachtwoord)) 
    .thenAccept(this::saveOrUpdateGebruiker) 
    .exceptionally(e -> 
    { 
     log.error("Fout bij het bijwerken van wachtwoord voor gebruiker: " + gebruikersnaam, e); 
     return null; 
    }); 

我预计呼叫saveOrUpdateGebruiker()在主线程中运行新创建的线程中的异步调用完成后。 但是,调用仍在另一个线程中,这会导致底层hibernate实现中出现问题。

有没有办法将CompletableFuture用于非阻塞异步调用,并且仍然能够在当前线程中使用结果?

回答

2

不自动没有。当执行由CompletableFuturesupplyAsyncthenAccept等提供的操作时,它们全部由线程池中的线程执行。这可以让你在你认为合适的情况下在主线程中进行“火和忘”操作并继续工作。

如果要在CompletableFuture完成后在当前线程中执行工作,则需要等待并使用isDone()和/或get()方法检查其完成情况。

但是,如果您这样做,那么在正常的Future(例如FutureTask)上使用CompletableFuture没有任何优势。

+0

所以最后,结果是阻塞同步调用? (因为get()函数) – Cloud

+1

那么,除非你轮询'isDone()'。这是您可以在当前线程上运行的唯一方法。 – Kayaman

1

您可以使用它使用您在参数传递执行人执行回调,这也可以是最终相同的是,一个你有来电

一样,该方法thenAcceptAsync(Runnable, Executor),可以控制线程用于执行您的回调代码

也见/执行人:This related Stackoverflow question

+1

这里有两个相互矛盾的答案。也许你应该修改你的答案,因为答案不是“是”,答案是“不,你不能在**当前线程**中运行它”。否则答案是好的。 – Kayaman

+0

不幸的是,这是不正确的。即使使用执行器技巧,也无法让代码在您调用'supplyAsync'的同一线程上运行。相关问题描述了一个将在当前线程上运行的执行程序,但是这个问题是关于当前线程,一个线程在池中(运行'supplyAsync'),并最终在当前线程中再次运行。如果提供描述的执行程序,它将是运行它的池线程(因为它是当前的“当前线程”)。 – Kayaman

1

使用CompletableFuture是您的方案矫枉过正。 CompletableFuture在其设计中是非阻塞的,当作业完成时,可以使用join()或轮询isDone()方法来收集结果,然后执行同步操作。如果只有一个进程继续向专用的ThreadPool发送任务,则使用CompletableFuture比CompletionServiceExecutorService没有任何优势。我写了一个简单的博客,其中CompletableFuture与传统的Threadpool相比非常合适:https://medium.com/@zhongzhongzhong/beauty-of-completablefuture-and-where-should-you-use-it-6ac65b7bfbe