如何等待被封闭的异步块完成?

问题描述 投票:0回答:2

我有一个问题 stream().forEach 在方法返回之前,它没有及时完成,这是怎么回事。

我的实体:

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Foo {
    private String a;
    private int b;
    private int c;
    private String d;
    private String e;
}

我有一个方法,它调用一个外部服务,该服务得到一个列表 Foo 然后对于该列表中的每个成员,它调用另外两个外部服务来填写 de 字段。

public List<Foo> getOrdresListe() {
    Foo[] fooArray = externalServiceOne.getFooList();
    Arrays.stream(fooArray).forEach((f) -> {
        CompletableFuture.supplyAsync(AsyncUtils.supplierWithCustomDependencies(() -> {
            Dob dob = externalServiceTwo.getDeeEntity(f.getA());
            f.setD(dob.getD());
            Efo efo = externalServiceThree.getEeeEntity(f.getA());
            f.setE(efo.getE());
            return f;
        }));
    });
    List<Foo> fooList = Arrays.asList(fooArray);
    return fooList; // when this statement is reached d and e fields are null.
}

由于一些性能问题(和一些最佳实践),我将 externalServiceTwo.getDeeEntityexternalServiceThree.getEeeEntity 异步地与一个自定义的供应商在调用服务时嵌入一些依赖关系。但主要问题是,当返回 fooList de 字段为空。

我的问题是如何等待所有异步执行结束后再返回 fooList ?

java asynchronous java-8 completable-future
2个回答
1
投票

你为什么不创建所有的 CompletableFutures作为中间操作,并在终端操作中等待所有异步执行完成。

Arrays.stream(fooArray).map((f) -> CompletableFuture.supplyAsync(AsyncUtils.supplierWithCustomDependencies(() -> {
                Dob dob = externalServiceTwo.getDeeEntity(f.getA());
                f.setD(dob.getD());
                Efo efo = externalServiceThree.getEeeEntity(f.getA());
                f.setE(efo.getE());
                return f;
            })
    )).forEach(fooCompletableFuture -> {
        try {
            fooCompletableFuture.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    });

1
投票

你可以直接记住这些异步任务,然后手动等待它们的完成。

public List<Foo> getOrdresListe() {
    Foo[] fooArray = externalServiceOne.getFooList();

    final List<CompletableFuture<Foo>> futures = new ArrayList<>(); // remember each

    Arrays.stream(fooArray).forEach((f) -> {
        futures.add(CompletableFuture.supplyAsync(
                AsyncUtils.supplierWithCustomDependencies(() -> {
            Dob dob = externalServiceTwo.getDeeEntity(f.getA());
            f.setD(dob.getD());
            Efo efo = externalServiceThree.getEeeEntity(f.getA());
            f.setE(efo.getE());
            return f;
        })));
    });

    for (CompletableFuture<Foo> future : futures) {
        future.join(); // wait for each
    }

    List<Foo> fooList = Arrays.asList(fooArray);
    return fooList;
}
© www.soinside.com 2019 - 2024. All rights reserved.