UUID.randomUUID()的CompletableFuture问题

时间:2019-01-24 11:31:38

标签: asynchronous java-8 uuid completable-future

因此,我决定开始在Java8中使用CompletableFuture,但我无法弄清楚此代码段出了什么问题:

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时会得到结果。
  • 调试时我能到达的最后一个断点是加入futureUUID final String uuid = futureUUID.join();时的那一行,然后程序停止,没有结果。

有人可以尝试向我解释为什么在使用UUID时出现这种奇怪的行为吗?

PS:我刚刚开始学习CompletableFuture,并想到了并行期货,然后偶然地来到了这里。

最诚挚的问候。

1 个答案:

答案 0 :(得分:5)

这与UUID无关,除了它的生成需要一些时间并且您无需等待完成。

由于所有操作都在后台线程中进行,并且您从using System.Collections; using System.Collections.Generic; using UnityEngine; public class Patrol0 : MonoBehaviour { public float speed; public Transform moveSpots; private float waitTime; public float StartwaitTime; public float MinX; public float MaxX; public float MinY; public float MaxY; void start() { moveSpots = GetComponentInParent<Transform>(); waitTime = StartwaitTime; moveSpots.position = new Vector2(Random.Range(MinX, MaxX), Random.Range(MinY, MaxX)); } private void Update() { transform.position = Vector2.MoveTowards(transform.position, moveSpots.position, speed * Time.deltaTime); if (Vector2.Distance(transform.position, moveSpots.position) < 0.2f) { if (waitTime <= 0) { moveSpots.position = new Vector2(Random.Range(MinX, MaxX), Random.Range(MinY, MaxX)); waitTime = StartwaitTime; } else { waitTime -= Time.deltaTime; } } } } 方法返回,因此JVM将确定不再有非守护进程线程正在运行并终止。

只需添加一个等待完成操作:

main

请注意,在原始代码中,您使用的是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调用。