有一天,我重写了执行不佳的多线程代码,该代码在Future.get()
某个时刻被阻塞:
public void serve() throws InterruptedException, ExecutionException, TimeoutException {
final Future<Response> responseFuture = asyncCode();
final Response response = responseFuture.get(1, SECONDS);
send(response);
}
private void send(Response response) {
//...
}
这实际上是一个用Java编写的Akka应用程序,具有1000个线程的线程池(原文如此!)–所有这些都在此get()
调用中被阻塞。 否则系统无法跟上并发请求的数量。 重构之后,我们摆脱了所有这些线程,只引入了一个,大大减少了内存占用。 让我们简化一下并显示Java 8中的示例。第一步是引入CompletableFuture
而不是普通的Future
(请参阅提示9 )。 很简单,如果:
- 您可以控制如何将任务提交给
ExecutorService
:只需使用CompletableFuture.supplyAsync(..., executorService)
而不是executorService.submit(...)
- 您处理基于回调的API:使用Promise
否则(如果您已经阻塞了API或Future<T>
),将有一些线程被阻塞。 这就是为什么现在诞生了这么多异步API的原因。 假设我们以某种方式重写了代码以接收CompletableFuture
:
public void serve() throws InterruptedException, ExecutionException, TimeoutException {
final CompletableFuture<Response> responseFuture