Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在未来成为一名听众<;Iterable<;A>&燃气轮机;到Iterable<;可上市未来<;B>&燃气轮机;通过拆分和运行_Java_Asynchronous_Concurrency_Guava_Future - Fatal编程技术网

Java 在未来成为一名听众<;Iterable<;A>&燃气轮机;到Iterable<;可上市未来<;B>&燃气轮机;通过拆分和运行

Java 在未来成为一名听众<;Iterable<;A>&燃气轮机;到Iterable<;可上市未来<;B>&燃气轮机;通过拆分和运行,java,asynchronous,concurrency,guava,future,Java,Asynchronous,Concurrency,Guava,Future,我正在寻找将ListenableFuture转换为单个ListenableFuture序列的最佳方法。这就是我要寻找的方法签名: public <A, B> Iterable<ListenableFuture<B>> splitAndRun( final ListenableFuture<Iterable<A>> elements, final Function<A, B> func, final

我正在寻找将
ListenableFuture
转换为单个
ListenableFuture
序列的最佳方法。这就是我要寻找的方法签名:

public <A, B> Iterable<ListenableFuture<B>> splitAndRun(
    final ListenableFuture<Iterable<A>> elements, 
    final Function<A, B> func, 
    final ListeningExecutorService executor
);

如果将
ListenableFuture
视为一个框,为了从该框中获取某些内容,必须阻止线程(调用
get
方法)

不确定实现
splitAndRun
方法是否能在某种程度上使您受益。您仍然有一个异步操作返回
ListenableFuture


不过,将
Iterable
作为单个
ListenableFuture
连接的反向操作可能很有用。如果要将多个异步计算收集到一个异步计算中,您可能需要使用它

这有两个部分。第一个是将
未来
转换为
未来
。这可以通过嵌套
Futures.transform
Iterables.transform
来实现(如果转换很快,请在另一个答案中详细说明)。下面是代码(尽管我已经将
Iterables.transform
替换为
列表.transform
,这将需要
未来的
,原因我稍后还会解释):

当然,列表中的每个
Future
都将在同一时间完成——只有在完成完整的
Future
输入时。也就是说,我们不能提前得到结果;我们只能以不同的格式获取它们(即,单个
Future
实例,而不是批量列表)。这是从
未来开始的必要限制

但是,如果转换很慢,或者某些输入可能失败,但其他输入可能成功,该怎么办?在这种情况下,我们希望分别转换每个输出。此外,我们希望确保转换只发生一次。我们的集合转换方法不提供此保证。因此,在示例代码中,输出上的每次迭代都将向执行者提交新任务,即使以前提交的任务可能已经完成。因此,仅当转换是轻量级的时,我们建议使用
Iterables.transform
和friends。(通常,如果你做重量级的事情,你的转换函数会抛出一个检查异常,<>代码>函数< /> >不允许。考虑这个提示:当然,你的例子碰巧不是触发提示)。
这在代码中意味着什么?基本上,我们将颠倒我在另一个答案中给出的操作顺序。我们将从
future转换为反向操作。是的,这很公平。我希望谷歌可能会有一些关于期货的聪明的集合,并根据它们的完成状态对它们进行迭代。不幸的是,这将是可怕的。考虑Chris Povirk的第二个答案作为解决你的问题的方法。经过一些调整,它只会导致一个等待组合未来的
get
。根据Mairbek Khadikov的回答,您需要在代码中至少有2个
get
s。在任何情况下,+1表示问题。这是一个很好的解决方案,因为它没有解释阻塞。不幸的是,在实践中,它与我最初的实现没有什么不同,因为在获取列表的第一个元素时有一个隐含块。这并不会使解决方案变得糟糕或错误,我喜欢它,但它必须等待初始列表可用。事实上,仔细想想,这是最接近“正确”答案的结果,因此我不妨将其标记为正确答案。以后可能发生的牵连块比现在必须发生的解释块要好。。。。虽然我确实错过了“knownSize”潜入其中;)是的,在我不太受欢迎的回答中提到后,我想我可以偷偷把它放在这里:)正如我在那里注意到的,如果你没有
知识
,那么你就不走运了。
public class CallableFunction<I, O> implements Callable<O>{
  private final I input;
  private final Function<I, O> func;

  public CallableFunction(I input, Function<I, O> func) {
    this.input = input;
    this.func = func;
  }

  @Override public O call() throws Exception {
    return func.apply(input);
  }
}

public <A, B> Iterable<ListenableFuture<B>> splitAndRun(
    final ListenableFuture<Iterable<A>> elements, 
    final Function<A, B> func, 
    final ListeningExecutorService executor
) throws InterruptedException, ExecutionException {
  return Futures.transform(elements, 
      new Function<Iterable<A>, Iterable<ListenableFuture<B>>>() {
    @Override
    public Iterable<ListenableFuture<B>> apply(Iterable<A> input) {
      return Iterables.transform(input, new Function<A, ListenableFuture<B>>() {
        @Override
        public ListenableFuture<B> apply(A a) {
          return executor.submit(new CallableFunction<A, B>(a, func));
        }
      });
    }
  }, executor).get();
}
final ListenableFuture<List<B>> transformed =
    Futures.transform(input, new Function<List<A>, List<B>>() {
      @Override
      public List<B> apply(List<A> inputs) {
        return Lists.transform(inputs, function);
      }
    });
List<ListenableFuture<B>> result = newArrayList();
for (int i = 0; i < knownSize; i++) {
  final int index = i;
  result.add(Futures.transform(transformed, new Function<List<B>, B>() {
    @Override
    public B apply(List<B> values) {
      return values.get(index);
    }
  }));
}
return result;
List<ListenableFuture<A>> individuals = newArrayList();
for (int i = 0; i < knownSize; i++) {
  final int index = i;
  individuals.add(transform(input, new Function<List<A>, A>() {
    @Override
    public A apply(List<A> values) {
      return values.get(index);
    }
  }));
}

List<ListenableFuture<B>> result = newArrayList();
for (ListenableFuture<A> original : individuals) {
  result.add(transform(original, function, executor));
}
return result;
List<ListenableFuture<B>> result = newArrayList();
for (int i = 0; i < knownSize; i++) {
  final int index = i;
  result.add(transform(input, new Function<List<A>, B>() {
    @Override
    public B apply(List<A> values) {
      return function.apply(values.get(index));
    }
  }, executor));
}
return result;