Lambda从入门到精通之三十七 CompletableFuture异步编程 handle方法使用详解

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方法则可以改变返回类型。