在Futures.transform中,使用Function和AsyncFunction有什么区别

时间:2014-06-05 00:06:54

标签: java guava future concurrent.futures

我知道Function的apply方法同步返回一个对象,并且AsyncFunction的apply应用异步运行并返回Future。

你能举个例子说明何时选择什么。

我看到的一个代码片段看起来像这样:

Futures.transform(someFuture, new AsyncFunction<A, B>() {
  public B apply(A a) {
    if (a != null) {
      return Futures.immediateFuture(a.getData())
    } else {
      return Futures.immediateFailedFuture(checkException(());
    }
  });
});

由于AsyncFunction内的值是立即返回的,为什么这里需要AsyncFunction?或者这只是我遇到的一个不好的例子?

4 个答案:

答案 0 :(得分:10)

您找到的代码片段是一个错误的示例,因为它使用AsyncFunction来同步计算某些内容。它不必要地冗长。

使用标准Function

,代码更清晰
Futures.transform(someFuture, new Function<A, B>() {
  public B apply(A a) {
    if (a != null) {
      return a.getData();
    } else {
      throw checkException();
    }
  });
});

当转换A到B的代码是异步时,您应该使用AsyncFunction。在您的示例中,代码最初可能是异步的,后来由程序员更改为使用Futures.immediateFuture() / Futures.immediateFailedFuture(),而该程序员并不打扰替换{{1 {}为AsyncFunction。或许他只是错过了重载方法。

答案 1 :(得分:1)

  

由于AsyncFunction内的值是立即返回的,   为什么需要AsyncFunction?或者这只是我的一个坏榜样   遇到了什么?

小心。这段代码生成一个匿名类的实例,并将该实例传递给transform方法。 transform方法将使用AsyncFunction是一个单独的线程。 Future返回的链从AsyncFunction检索结果并返回Future的结果。此代码仍涉及异步处理。

在您希望的时候使用异步处理,并且可以在执行其他操作时继续工作。

答案 2 :(得分:1)

您提供的代码段是一个不好的例子,无论谁编写它都应该使用Function。

Futures.transform()用于跟进一些异步过程。让我们将其称为“异步进程1”的“ap1”。当ap1完成时,由transform链接的函数将执行。 现在,让我们讨论可以使用Futures.transform()链接的两种类型的函数。

    // AsyncFunction() example:
    ListenableFuture<B> future2 = Futures.transform(future1, new AsyncFunction<A, B>() {
      public ListenableFuture<B> apply(A a) {
        if (a != null) {
          ListenableFuture<B> future3 = asyncCallToOtherService(a);
          return future3;
        }
        else {
          return Future.immediateFuture(null);
        }
      });
    });

    // more complex AsyncFunction() example:
    ListenableFuture<B> future2 = Futures.transform(future1, new AsyncFunction<A, B>() {
      public ListenableFuture<B> apply(A a) {
        if (a != null) {
          ListenableFuture<C> future3 = asyncCallToOtherService(a);
          return Futures.transform(future3, new Function<C, B>() {
            @Override
            public B apply(C c) {
              B b = new B();
              b.setResult(c.getStatus());
              return b;
            }
          });
        }
        else {
          return Future.immediateFuture(null);
        }
      });
    });

    // Function() example:
    ListenableFuture<B> future2 = Futures.transform(future1, new Function<A, B>() {
      public B apply(A a) {
        if (a != null) {
          B b = new B();
          b.setResult(a.getStatus());
          return b;
        }
        else {
          return null;
        }
      });
    });
  1. 当apply()中的代码产生另一个异步进程2(AP2)时,应该使用AsyncFunction()。这形成了一系列彼此跟随的异步调用:AP1-> AP2。
  2. 当从AP1转换结果不需要任何其他异步进程时,应使用Function()。而它所做的只是将结果Object1以同步方式转换为其他Object2。
  3. AsyncFunction()稍微重一些并导致单独的线程,因此每当我们不需要旋转AP2时我们应该使用Function()。
  4. 可以根据需要将多个函数和AsyncFunction链接在一起,以便创建完整的工作流程。示例“更复杂的AsyncFunction()示例”链A~&gt; C-> B变换,其中A~> C是异步的。

答案 3 :(得分:0)

使用AsyncFunction在这里很有意义。如果你想在Function中的apply()方法中抛出一些已检查的异常,它会抱怨它没有被处理。你不能将它从apply()中删除,因为它被覆盖了。因此,如果要抛出一些已检查的异常,AsyncFunction应该是一个有效的解决方案。对于那些说给定示例很糟糕且给出函数示例的人,可以尝试编译吗?