说我有两个重量级的IO阻止操作,即findMatchInSomeDB()和getDetailsFromOtherDB(String objectKey)。此外,我希望它们在后台运行,并使用番石榴期货将它们链接在一起,因为一个依赖于另一个的结果(我知道这可以在一个简单的Callable中按顺序完成,但对于说明目的):
下面的consumeChain
和consumeChainAsync
方法之间是否存在实际或细微差别?
import com.google.common.base.Function;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class Consumer
{
private final Retriever retriever;
private final ListeningExecutorService executorSvc;
public Consumer(Retriever retriever, ListeningExecutorService executorSvc)
{
this.retriever = retriever;
this.executorSvc = executorSvc;
}
private void consumeChain(String searchCriteria) throws Exception
{
ListenableFuture<String> futureMatch = executorSvc.submit(
() -> retriever.findMatchInSomeDB(searchCriteria));
Function<String, DataObject> keyToDataObj = objectKey ->
retriever.getDetailsFromOtherDB(objectKey);
// using "real" executor service so transform function runs
// in the background
ListenableFuture<DataObject> futureDataObj = Futures.transform(
futureMatch, keyToDataObj, executorSvc);
// ...do some other stuff in this thread...
// do something with futureDataObj result
futureDataObj.get();
}
private void consumeChainAsync(String searchCriteria) throws Exception
{
ListenableFuture<String> futureMatch = executorSvc.submit(
() -> retriever.findMatchInSomeDB(searchCriteria));
AsyncFunction<String, DataObject> keyToDataObj = objectKey ->
{
return executorSvc.submit(
() -> retriever.getDetailsFromOtherDB(objectKey));
};
// using DirectExecutor because the transform function
// only creates and submits a Callable
ListenableFuture<DataObject> futureDataObj = Futures.transformAsync(
futureMatch, keyToDataObj, MoreExecutors.directExecutor());
// ...do some other stuff in this thread...
// do something with futureDataObj
futureDataObj.get();
}
}
据我所知,两者都将通过executorSvc
运行每个重量级操作,并且都将传播取消和/或执行失败。
似乎transformAsync
的唯一要点(而不是仅将transform
与DirectExecutor以外的执行器一起使用)是因为您正在使用返回ListenableFuture的API,而不是直接运行操作。我想念什么吗?
答案 0 :(得分:0)
似乎
transformAsync
的唯一要点(而不是仅将transform
与DirectExecutor以外的执行器一起使用)是因为您正在使用返回ListenableFuture的API,而不是直接运行操作。
我认为就是这个主意。
但是,我可以想到一个小的区别,它使transformAsync
稍微好一些:如果您在输出cancel(true)
上调用Future
,则当前won't interrupt the thread that runs getDetailsFromOtherDB
的transform
。相反,transformAsync
将(通过对从cancel(true)
返回的ListenableFuture
上的ListeningExecutorService
进行调用)。 transform
应该传播中断,但是正确执行此操作有些微妙之处,请参见上面的链接。