UUID.randomUUID()的CompletableFuture问题

Moh*_*ADI 1 uuid asynchronous java-8 completable-future

所以我决定开始使用 CompletableFutureJava8,我无法弄清楚这个片段有什么问题:

public static void main(String...strings) throws Exception {
    final Supplier<User> makeUserSupplier = () -> makeUser();
    final Supplier<String> uuidSupplier =  () -> makeUUID();

    final CompletableFuture<User> futureUser = CompletableFuture.supplyAsync(makeUserSupplier);
    final CompletableFuture<String> futureUUID = CompletableFuture.supplyAsync(uuidSupplier);

    CompletableFuture.allOf(futureUser, futureUUID)
        .thenApplyAsync(aVoid -> {
            final User user = futureUser.join();
            final String uuid = futureUUID.join();
            return "received user + " + user + " and uuid is " + uuid ;
        })
        .handle((ok, e) -> {
            System.out.println("ok----" + ok);
            System.out.println("e----" + e);
            return null;
        });
}
    private static User makeUser() throws RuntimeException {
//        throw new RuntimeException("lkj");
        return new User(1L, "mm", "ll", "kk");
    }
    private static String makeUUID() throws RuntimeException {
        return UUID.randomUUID().toString();
//        return "dummy";
    }
Run Code Online (Sandbox Code Playgroud)

User类定义为:

@Data
@AllArgsConstructor
public class User {
    private Long id;
    private String username;
    private String password;
    private String role;
}
Run Code Online (Sandbox Code Playgroud)

我得到的行为是:

  • 没有什么是印在我的控制台当我使用UUID.randomUUID().toString(),我得到的结果,当我使用一些随机的String.
  • 调试时我能够达到的最后一个断点是当我加入futureUUID时的行final String uuid = futureUUID.join();,然后我的程序停止而没有结果.

有人可以试着向我解释为什么我在使用UUID时会遇到这种奇怪的行为吗?

PS:我刚开始学习CompletableFuture并考虑并行期货,然后不小心来到了这里.

最好的祝福.

Hol*_*ger 5

这与UUID无关,除了它的生成需要一些时间而你不等待完成.

由于所有操作都在后台线程中发生,并且您从main方法返回,因此JVM将确定没有非Daemon线程正在运行并终止.

只需添加等待完成操作:

final Supplier<User> makeUserSupplier = () -> makeUser();
final Supplier<String> uuidSupplier =  () -> makeUUID();

final CompletableFuture<User> futureUser = CompletableFuture.supplyAsync(makeUserSupplier);
final CompletableFuture<String> futureUUID = CompletableFuture.supplyAsync(uuidSupplier);

CompletableFuture.allOf(futureUser, futureUUID)
    .thenApplyAsync(aVoid -> {
        final User user = futureUser.join();
        final String uuid = futureUUID.join();
        return "received user + " + user + " and uuid is " + uuid ;
    })
    .handle((ok, e) -> {
        System.out.println("ok----" + ok);
        System.out.println("e----" + e);
        return null;
    })
    .join(); // wait for completion
Run Code Online (Sandbox Code Playgroud)

请注意,在原始代码中,您使用的是.allOf(futureUser, futureUser)代替.allOf(futureUser, futureUUID),因此链接操作可能会在futureUUID尚未完成时执行,这可能导致工作线程在futureUUID.join()调用中被阻止.

如果你使用的话,你的代码会简单得多

final CompletableFuture<User> futureUser = CompletableFuture.supplyAsync(() -> makeUser());
final CompletableFuture<String> futureUUID = CompletableFuture.supplyAsync(() -> makeUUID());

futureUser.thenCombineAsync(futureUUID, (user, uuid) -> {
        return "received user + " + user + " and uuid is " + uuid;
    })
    .handle((ok, e) -> {
        System.out.println("ok----" + ok);
        System.out.println("e----" + e);
        return null;
    })
    .join(); // wait for completion
Run Code Online (Sandbox Code Playgroud)

因为在工作线程中allOf不需要join()调用,所以也可以免受错误的影响.