【问题标题】:Guava Futures.transform with "Real" Executor vs. transformAsync with DirectExecutorGuava Futures.transform 与“Real” Executor 与 transformAsync 与 DirectExecutor
【发布时间】:2018-10-27 02:40:01
【问题描述】:

假设我有两个重量级的 IO 阻塞操作,findMatchInSomeDB() 和 getDetailsFromOtherDB(String objectKey)。此外,我希望它们在后台运行,并使用 Guava Futures 将它们链接在一起,因为一个依赖于另一个 的结果(我知道这可以在一个简单的 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 时。我错过了什么吗?

【问题讨论】:

    标签: java multithreading asynchronous guava


    【解决方案1】:

    似乎transformAsync(而不是仅将transform 与 DirectExecutor 以外的执行程序一起使用)的唯一意义在于,当您使用返回 ListenableFuture 而不是直接运行操作的 API 时。

    我认为是这样的。

    但是,我可以想到一个使transformAsync 稍微好一点的小区别:如果您在输出Future 上调用cancel(true),则transform 当前为won't interrupt the thread that runs getDetailsFromOtherDB。相反,transformAsync 将(通过在从ListeningExecutorService 返回的ListenableFuture 上调用cancel(true))。 transform 应该传播中断,但要做到这一点有一些微妙之处,在上面的链接中有介绍。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-22
      • 1970-01-01
      相关资源
      最近更新 更多