我想要填充Person
。许多setter方法需要一些时间来填充,因为数据是从DB调用提供的,可能需要一些时间(超过10秒)才能返回。
我正在寻找在将Person
返回给调用方法之前异步填充mutators的最佳方法。
以下是一个例子:
Person p = service.getPersonById(id);
// populate from DMV DB
p.setTickets(dmvService.getTicketsById(id)); // takes 15 seconds to return data
p.setAccidentRecord(dmvService.getAccidentsById(id)); // takes 10 seconds.
...
...
return p;
我希望能够异步运行我的方法(setTickets
,setAccidentRecord
等),以将我的加载时间从25秒减少到15秒左右。
答案 0 :(得分:2)
CompletableFuture
†就是故障单。它是一个monadic,可链接的类,可以轻松管理线程外计算。
未来代表将在未来某个时间完成并产生结果的计算。它可能已经完成,或者在某些后台线程中可能需要一段时间。 CompletableFuture
建立在这个核心概念的基础上,允许您将各种其他转换和处理程序附加到现有的未来。
Person p = service.getPersonById(id);
CompletableFuture.allOf(
CompletableFuture.supplyAsync(() -> dmvService.getTicketsById(id))
.thenAccept(p::setTickets),
CompletableFuture.supplyAsync(() -> dmvService.getAccidentsById(id))
.thenAccept(p::setAccidentRecord)
).join();
return p;
在您的情况下,您可以使用supplyAsync
在后台主题中运行getTicketsById
和getAccidentsById
。由于您希望在这些方法返回时调用相应的setter,您可以使用thenAccept
来表示,"当该方法返回时,将值提供给此setter"。
您有两个背景计算,并且您不想在两个完成之前返回。用allOf
将这两个期货包装成一个更大的期货让我们在那里。 allOf
未来本身并未完成,直到两个内部期货都完成为止。
最后,我们join
allOf
未来,在继续之前等待它完成。如果这些代码中的任何一个可能抛出异常,那么join
将自己抛出该异常 - 尽管它将被包装在CompletionException
中 - 因此如果您愿意,可以在其周围添加try / catch
†不幸的是,Java首次尝试这个概念Future
,是一个动力不足,乏善可陈的阶级。他们用CompletableFuture
做对了,但是Future
偷走了理想的名字。