CompletableFuture的handle方法可以对结果再次进行处理,将正常返回结果和异常结果作为参数传入定义的函数中计算,返回新的类型的计算结果。
CompletableFuture handle(BiFunction fn)方法的参数是一个二元的函数,处理函数有两个参数R apply(T t, U u),第一个是业务逻辑处理结果,第二个是异常结果,二者其中一个总是为null,二者作为参数传入执行函数。
我们来看demo:
import java.io.Serializable;
import java.util.concurrent.CompletableFuture;
/**
* 使用CompletableFuture异步编程 handle
* @author www.itzhimei.com
*/
public class FutureTest_11 {
public static void main(String[] args) throws Exception {
//正常执行
Serializable join = CompletableFuture.supplyAsync(() -> FutureTest_11.getTaskResult(500, "Test Task 2"))
.handle((x, e) -> {
if (e != null) {
return e;
} else {
//改变返回的类型 String->Integer
return 1;
}
}).join();
System.out.println(join);
/* 输出
1
*/
Serializable join2 = CompletableFuture.supplyAsync(() -> FutureTest_11.getTaskResultWithException(500, "Test Task 2"))
.handle((x, e) -> {
if (e != null) {
return e;
} else {
//改变返回的类型 String->Integer
return 1;
}
}).join();
System.out.println(join2);
/* 输出
java.util.concurrent.CompletionException: java.lang.RuntimeException: 执行异常了
*/
}
public static String getTaskResult(long sleepTime, String task) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
return task;
}
public static String getTaskResultWithException(long sleepTime, String task) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
throw new RuntimeException("执行异常了");
//return task;
}
}
/* 输出
1
java.util.concurrent.CompletionException: java.lang.RuntimeException: 执行异常了
*/
这里的返回结果比较有趣,因为我们在计算函数中对正常计算结果进行了转换,统一都从String转换为了Integer,而异常时候的类型可以理解为String,此时最终的类型不确定到底是那哪种,所以程序定义成了Serializable类型,你也可以定义为Object类型的返回结果。
还要注意的是handle方法和前面讲的whenComplete方法非常相似,二者的区别主要在于方法的参数和返回结果,whenComplete也是将正常结果和异常传入,但是返回结果类型不会修改,需要和传入参数保持一致,handle方法则可以改变返回类型。