使用“真实”执行器的Guava Futures.transform与使用DirectExecutor的transformAsync

时间:2018-10-27 02:40:02

标签: java multithreading asynchronous guava

说我有两个重量级的IO阻止操作,即findMatchInSomeDB()和getDetailsFromOtherDB(String objectKey)。此外,我希望它们在后台运行,并使用番石榴期货将它们链接在一起,因为一个依赖于另一个的结果(我知道这可以在一个简单的Callable中按顺序完成,但对于说明目的)

下面的consumeChainconsumeChainAsync方法之间是否存在实际或细微差别?

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,而不是直接运行操作。我想念什么吗?

1 个答案:

答案 0 :(得分:0)

  

似乎transformAsync的唯一要点(而不是仅将transform与DirectExecutor以外的执行器一起使用)是因为您正在使用返回ListenableFuture的API,而不是直接运行操作。

我认为就是这个主意。

但是,我可以想到一个小的区别,它使transformAsync稍微好一些:如果您在输出cancel(true)上调用Future,则当前won't interrupt the thread that runs getDetailsFromOtherDBtransform 。相反,transformAsync将(通过对从cancel(true)返回的ListenableFuture上的ListeningExecutorService进行调用)。 transform 应该传播中断,但是正确执行此操作有些微妙之处,请参见上面的链接。