繁体   English   中英

然后应用于CompletableFuture

[英]thenApply in CompletableFuture

在下面的代码中

public CompletableFuture<String> getMyFuture(String input)
    {   
        CompletableFuture<String> future = new CompletableFuture<String>().thenApply((result) -> result+ "::");
        ExecutorService service = Executors.newFixedThreadPool(6);
        service.submit(() -> {      
            try {
                future.complete(getResult(input));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return future;
    }

    public String getResult(String input) throws InterruptedException
    {
        Thread.sleep(3000);
        return "hello "+ input +" :" + LocalTime.now();
    }

我期望输出包含尾部的“ ::”,但程序不是“ hello first:16:49:30.231”我的apply实现正确吗?

您正在调用第一行获得的CompletionStage complete()方法(在此处称为“ thenApply”方法)。

如果您打算用某个字符串值( future.complete(getResult(input)) )完成CompletableFuture并应用一些函数,则最好将thenApply()放在最后(返回未来)。

public CompletableFuture<String> getMyFuture(String input)
    {
        CompletableFuture<String> future = new CompletableFuture<String>();
        ExecutorService service = Executors.newFixedThreadPool(6);
        service.submit(() -> {
            try {
                future.complete(getResult(input));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return future.thenApply(result -> result+ "::");
    }

我不知道如何以更容易理解的方式解释它。 但简而言之: 您正在对 Runnable 错误的对象引用调用complete()方法

您正在创建两个 CompletableFuture实例。 第一个是通过new CompletableFuture<String>()创建的,它将永远不会完成,您甚至不会保留对其进行引用的引用,从而无法完成。

通过在第一个函数上调用.thenApply((result) -> result+ "::")创建的第二个函数,可以在第一个函数完成后通过评估指定的函数来完成,并使用第一个函数的结果作为函数的参数。 但是,由于第一个永远不会完成,因此该功能变得无关紧要。

但是CompletableFuture实例可以由任何人完成,而不仅仅是传递给链接方法的函数。 完成的可能性甚至在班级名称中突出显示。 如果进行了多次完成尝试,那么结果将是第一个赢得比赛,并且所有后续完成尝试都将被忽略。 在您的代码中,您只有一次完成尝试,它将使用getResult返回的值成功完成它,而无需进行任何修改。

您可以更改代码以保留对第一个CompletableFuture实例的引用,以手动complete它,以便使用传递给thenApply的函数来完成第二个thenApply ,但是另一方面,这里不需要手动完成:

public CompletableFuture<String> getMyFuture(String input) {   
    ExecutorService service = Executors.newFixedThreadPool(6);
    return CompletableFuture.supplyAsync(() -> getResult(input), service)
                            .thenApply(result -> result + "::");
}
public String getResult(String input) {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
    return "hello "+ input +" :" + LocalTime.now();
}    

将执行程序指定为supplyAsync ,将使用该执行程序对函数进行评估。 不需要更多。

不用说,这只是举例。 您永远不应创建一个临时线程池执行程序,因为线程池执行程序的全部目的是允许重用线程(并且您仅使用这六个线程之一),并且在使用后应将其关闭。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM