Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java.util.concurrent.CompletableFuture中的异常传播_Java_Java.util.concurrent_Completable Future_Forkjoinpool - Fatal编程技术网

java.util.concurrent.CompletableFuture中的异常传播

java.util.concurrent.CompletableFuture中的异常传播,java,java.util.concurrent,completable-future,forkjoinpool,Java,Java.util.concurrent,Completable Future,Forkjoinpool,有两段代码 在第一个任务中,我们从总是抛出一些异常的任务创建CompletableFuture。然后,我们将“例外”方法应用于这个未来,然后是“接受”方法。我们不会将Accept方法返回的新future分配给任何变量。然后我们对原始未来调用“join”。我们看到的是,调用了“异常”方法以及“thenAccept”。我们看到它是因为他们在输出中打印了适当的行。但这种例外并没有被“例外”方法所抑制。抑制异常并为我们提供一些默认值,这正是我们在本例中对“异常”的期望 在第二个代码段中,我们做了几乎相同

有两段代码

在第一个任务中,我们从总是抛出一些异常的任务创建CompletableFuture。然后,我们将“例外”方法应用于这个未来,然后是“接受”方法。我们不会将Accept方法返回的新future分配给任何变量。然后我们对原始未来调用“join”。我们看到的是,调用了“异常”方法以及“thenAccept”。我们看到它是因为他们在输出中打印了适当的行。但这种例外并没有被“例外”方法所抑制。抑制异常并为我们提供一些默认值,这正是我们在本例中对“异常”的期望

在第二个代码段中,我们做了几乎相同的事情,但将新返回的future分配给变量并对其调用“join”。在这种情况下,将抑制预期异常

从我的观点来看,对于第一部分,一致性行为要么不抑制异常,要么不调用“exception”和“thenAccept”,要么调用exception和suppress exception

为什么我们要在两者之间呢

第一段:

public class TestClass {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(TestClass::doSomethingForInteger);

        future.exceptionally(e -> {
                    System.out.println("Exceptionally");
                    return 42;
                })
                .thenAccept(r -> {
                    System.out.println("Accept");
                });

        future.join();
    }

    private static int doSomethingForInteger() {
        throw new IllegalArgumentException("Error");
    }
}
public class TestClass {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(TestClass::doSomethingForInteger);

        CompletableFuture<Void> voidCompletableFuture = future.exceptionally(e -> {
            System.out.println("Exceptionally");
            return 42;
        })
                .thenAccept(r -> {
                    System.out.println("Accept");
                });

        voidCompletableFuture.join();
    }

    private static int doSomethingForInteger() {
        throw new IllegalArgumentException("Error");
    }
}
公共类TestClass{
公共静态void main(字符串[]args){
CompletableFuture=CompletableFuture.supplyAsync(TestClass::doSomethingForInteger);
未来。例外(e->{
系统输出打印项次(“例外”);
返回42;
})
.然后接受(r->{
系统输出打印项次(“接受”);
});
future.join();
}
私有静态int-doSomethingForInteger(){
抛出新的IllegalArgumentException(“错误”);
}
}
第二段:

public class TestClass {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(TestClass::doSomethingForInteger);

        future.exceptionally(e -> {
                    System.out.println("Exceptionally");
                    return 42;
                })
                .thenAccept(r -> {
                    System.out.println("Accept");
                });

        future.join();
    }

    private static int doSomethingForInteger() {
        throw new IllegalArgumentException("Error");
    }
}
public class TestClass {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(TestClass::doSomethingForInteger);

        CompletableFuture<Void> voidCompletableFuture = future.exceptionally(e -> {
            System.out.println("Exceptionally");
            return 42;
        })
                .thenAccept(r -> {
                    System.out.println("Accept");
                });

        voidCompletableFuture.join();
    }

    private static int doSomethingForInteger() {
        throw new IllegalArgumentException("Error");
    }
}
公共类TestClass{
公共静态void main(字符串[]args){
CompletableFuture=CompletableFuture.supplyAsync(TestClass::doSomethingForInteger);
CompletableFuture void CompletableFuture=未来。例外情况下(e->{
系统输出打印项次(“例外”);
返回42;
})
.然后接受(r->{
系统输出打印项次(“接受”);
});
voidCompletableFuture.join();
}
私有静态int-doSomethingForInteger(){
抛出新的IllegalArgumentException(“错误”);
}
}

没有“抑制异常”这样的事情。当您异常地调用
时,您正在创建一个新的未来,该未来将使用前一阶段的结果完成,或者如果前一阶段异常地完成,则使用评估函数的结果完成。前一阶段,即您正在调用的
异常
的未来不会受到影响

这适用于链接依赖函数或操作的所有方法。这些方法中的每一种都创造了一个新的未来,并将按文档记录的方式完成。它们都不会影响您在其上调用方法的现有未来

下面的例子可能会更清楚:

CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    return "a string";
});

CompletableFuture<Integer> f2 = f1.thenApply(s -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
    return s.length();
});

f2.thenAccept(i -> System.out.println("result of f2 = "+i));

String s = f1.join();
System.out.println("result of f1 = "+s);

ForkJoinPool.commonPool().awaitQuiescence(1, TimeUnit.DAYS);

如前所述,每个链式方法都会创建一个新的阶段,因此保留对最后一个链式方法(即最后一个阶段)返回的阶段的引用适用于获得最终结果。但取消此阶段只会取消最后一个阶段,而不会取消任何先决阶段。此外,取消后,最后一个阶段不再依赖于其他阶段,因为它已经通过取消完成,并且能够报告此异常结果,而其他现在不相关的阶段仍在后台进行评估。

问题有点不同。我完全理解连锁不是一种单一未来的建设者。但正如您在第一段代码中看到的,我不会存储通过链接到任何变量返回的未来。我加入的未来并不依赖于任何其他未来。那么为什么要调用“异常”呢?链接到未来的操作将尝试完成新创建的未来,无论您是否存储对它的引用。该代码如何知道您是否存储了对未来的引用?新创建的未来依赖于原始未来,而不是相反,对吗?为什么最初的未来应该试图完成新创造的未来?对不起,也许这是一个愚蠢的问题,但我想理解它是这样做的,因为你告诉过它。在将来异常地调用
,就像注册一个监听器来完成它一样。未来并不关心监听器做什么,它与
然后运行
等没有什么不同。为了保持这种类比,您只能通过取消注册监听器来选择退出监听器,这需要对监听器的引用。如果您不保留它,侦听器仍将运行,没有任何取消注册的能力。同样地,当您没有保留对新创建的future的引用时,您无法取消它,因此您失去了选择退出的可能性。因此,ok、“Exception”和任何其他此类方法不仅创建并返回新的future对象,而且还向应用它们的对象注册侦听器。但是,如果我们存储了引用并在其上有joint,异常将不会传播,我们将获得由“exception”提供的存根,对吗。这就是我想了解的。非常感谢。
CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("initial stage");
    return "";
}).thenApply(s -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("second stage");
    return s;
}).thenApply(s -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("third stage");
    return s;
}).thenAccept(s -> {
    System.out.println("last stage");
});

f.cancel(true);
report("f", f);

ForkJoinPool.commonPool().awaitQuiescence(1, TimeUnit.DAYS);