代码之家  ›  专栏  ›  技术社区  ›  Incepter

uuid.randomuuid()的复杂未来问题

  •  1
  • Incepter  · 技术社区  · 6 年前

    所以我决定开始使用 CompletableFuture 在java8中,我无法找出这段代码有什么问题:

    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";
        }
    

    何处 User 类定义为:

    @Data
    @AllArgsConstructor
    public class User {
        private Long id;
        private String username;
        private String password;
        private String role;
    }
    

    我的行为是:

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

    有人能解释一下为什么我在使用UUID时会有这种奇怪的行为吗?

    附言:我刚开始学 复杂的未来 想到了平行的未来,就不小心想到了这一点。

    最好的问候。

    1 回复  |  直到 6 年前
        1
  •  5
  •   Holger    6 年前

    这与UUID无关,只是它的生成需要一些时间,而您不需要等待完成。

    因为所有操作都发生在后台线程中,而您将从 main 方法,jvm将确定不再运行任何非守护进程线程并终止。

    只需添加等待完成操作:

    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
    

    请注意,在原始代码中, .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
    

    也不受以下错误的影响 allOf ,因为没有 join() 工作线程中需要调用。