我在这里有此功能:
Function<Integer, Integer> func = (value) -> value + 5;
func = func.andThen((value) -> {
//Imagine that here some code executed and raised an exception, I'm throwing it
//manually just for the sake of this example.
throw new RuntimeException("failed");
});
func = func.andThen((value) -> {
System.out.println("Reached last function !");
return value;
});
executeFunction(func);
现在,您可以看到我在第一个andThen方法中抛出了运行时异常。那是因为我想防止第二个andThen被执行。那是最好的方法吗?
此外,我注意到,如果我在另一个线程(异步)中执行此功能,则异常不会打印在控制台中,并且我想知道该异常发生了。
private static void executeFunction(Function<Integer, Integer> function) {
CompletableFuture.supplyAsync(() -> function.apply(100));
}
在这种情况下,如果我想确保记录了异常,但是并没有执行andThen链中的下一个函数,我应该记录并抛出吗?这不是ati模式吗?
答案 0 :(得分:1)
实例化和引发大量异常可能变得非常昂贵,这就是为什么应该将它们限制在特殊情况下的原因。相反,您可以使用Optional进行控制:
>>> combine_lists([1, 2, 3], [4])
[1, 4, 2, 3]
>>> combine_lists([1], [4, 5, 6])
[1, 4, 5, 6]
>>> combine_lists([], [4, 5, 6])
[4, 5, 6]
>>> combine_lists([1, 2], [4, 5, 6])
[1, 4, 2, 5, 6]
答案 1 :(得分:0)
您可以编写函数/可运行程序的包装,在任务失败时记录并退出。像这样:
class Runnables
{
public static Runnable trying(Runnable... runnables)
{
return () ->
{
int successes = 0;
try
{
for(Runnable runnable : runnables)
{
runnable.run();
successes++;
}
}
catch(Throwable t)
{
logger.error("Exception thrown from "+successes+"th runnable: ",t);
}
};
}
}
然后:
private static void executeFunction(Runnable... runnables)
{
CompletableFuture.supplyAsync(Runnables.trying(runnables));
}
答案 2 :(得分:0)
您可以使用CompletableFuture.thenApply
方法来获得所需的行为。例如:
public class Answer {
public static void main(String[] args) {
Function<Integer, Integer> fn0 = v -> v + 5;
Function<Integer, Integer> fn1 = v -> {
throw new RuntimeException("failed");
};
Function<Integer, Integer> fn2 = v -> {
System.out.println("Reached last function !");
return v;
};
CompletableFuture.supplyAsync(() -> fn0.apply(100))
.thenApply(fn1)
.thenApply(fn2)
.exceptionally(throwable -> {
// next line prints the exception thrown by fn1, wrapped in java.util.concurrent.CompletionException
System.out.println("Failed with error: " + throwable);
return 0; // default value, used when exception is thrown
});
}
}
CompletableFuture
链基本上会被“开箱即用”异常中断,因此不需要其他处理。
或者,如果您想使用更通用的方法:
public class Answer {
public static void main(String[] args) {
executeAsync(() -> stepOne(100))
.thenApply(Answer::stepTwo)
.thenApply(Answer::finalStep)
.exceptionally(Answer::handleException);
}
private static CompletableFuture<Integer> executeAsync(Supplier<Integer> task) {
return CompletableFuture.supplyAsync(task::get);
}
private static Integer stepOne(Integer value) {
return value + 5;
}
private static Integer stepTwo(Integer value) {
throw new RuntimeException("failed");
}
private static Integer finalStep(Integer value) {
System.out.println("Reached last function !");
return value;
}
private static Integer handleException(Throwable throwable) {
// next line prints the exception thrown by any step before, wrapped in java.util.concurrent.CompletionException
System.out.println("Failed with error: " + throwable);
return 0; // default value
}
注意:
使用thenApply
可以根据需要链接任意数量的函数调用
在最后一个示例中,同一类内的方法可以被其他类(不一定是静态类)中的方法替换