JDK8 CompletableFuture常用Api使用梳理

        在JDK8中,CompletableFuture作为一个全新的任务执行框架类,它可以通过简单的api实现任务的异步执行、任务之间的协同、以及任务编排等功能。在CompletableFuture中,每个任务可以被同步的执行、也可以被异步的执行(通过提交到线程池中来实现)。在CompletableFuture中,几乎每一个操作都有三套API,API形式如:xxx(...)、xxxAsync(...)、xxxAsync(...,Executor executor),xxx表示操作名称。其中xxx(...)形式的操作表示该操作是同步执行的、xxxAsync(...)和xxxAsync(...,Executor executor)表示该操作是异步执行的,xxxAsync(...,Executor executor)表示使用指定的线程池来完成异步操作,xxxAsync(...)表示使用默认的线程池来完成异步操作。这个默认的线程池是一个ForkJoinPool类型的线程池,默认的线程数数量为:当前CPU的核数减一,最小线程数为一。可以通过在应用启动时设置参数 java.util.concurrent.ForkJoinPool.common.parallelism 来改变默认线程池线程数量。

       此外,任务结束的方式有两种,一种以正常执行完成的方式来结束,另一种以在执行过程中抛出异常的方式来结束。当任务的结束状态为异常结束状态时,调用和获取结果相关的api都会抛出异常,比如get()、joiner()接口等等。

下面内容是对CompletableFuture常用的API进行了梳理,为了方便,所有的操作都采用xxx(..)形式(即同步执行)的API来作为演示。

1、任务创建

//直接创建任务,并设置返回值
CompletableFuture<String> task1 = CompletableFuture.completedFuture("hi");

//创建一个不带返回值的异步执行任务
CompletableFuture<Void> taks2 = CompletableFuture.runAsync(() -> {
    System.out.println("hi");
});

//创建一个带有返回值的异步执行任务
CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> {
    return "hi";
});

2、获取任务结果

//阻塞等待获取结果
try {
    String res1 = CompletableFuture.completedFuture("hi").get();
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

//有限等待获取结果,指定时间内未获取结果,则抛出TimeoutException
try {
    String res2 = CompletableFuture.completedFuture("hi").get(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
} catch (TimeoutException e) {
    e.printStackTrace();
}

//立刻获取结果,如果未获得结果,则返回默认值
String res3 = CompletableFuture.completedFuture("hi").getNow("NULL");

//阻塞等待获取结果,如果任务执行过程中抛出异常,该调用则会抛出非必检的CompletionException
String res4 = CompletableFuture.completedFuture("hi").join();

3、设置任务执行过程抛出异常时,返回的默认值

CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
    return Integer.parseInt("9a");  //解析Int类型数据,抛出异常
}).exceptionally(ex -> {
    ex.printStackTrace();   //异常处理,此处选择打印调用异常栈

    return 999;             //返回默认值999
});

4、设置任务完成后的动作,不管任务是以正常执行完成的方式来结束,还是以抛出异常的方式来结束,该动作都会执行

CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
    return Integer.parseInt("9a");
}).whenComplete((res, ex) -> {
    if (ex == null) {
        System.out.println("任务返回的结果是 " + res);
    }
    System.out.println("任务执行过程中发生了异常...");
    ex.printStackTrace();
});

5、手动终止任务执行

//手动结束任务,并设置返回值为100。如果该手动结束发生在任务执行完成前,则设置成功返回true,否则设置无效返回false
CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> {
    return Integer.parseInt("1");
});
boolean setIsSuccess1 = task1.complete(100);

/**手动结束任务,并且设置以抛出 RunntimeException 异常来结束。
 * 如果该手动结束发生在任务执行完成前,则设置成功返回true,否则设置无效返回false
 * 如果设置成功,则后续调用和获取任务结果相关的api,比如get()、joiner()等接口,都会抛出异常
 * */
CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
    return Integer.parseInt("2");
});
boolean setIsSuccess2 = task2.completeExceptionally(new RuntimeException("Manual Except End"));

/**手动取消该任务,如果发生在该任务执行完成前,则取消成功返回true,否则返回false。
 * 其中,cancel(true) 和 cancel(false) 效果一样,该参数在 CompletableFeature 中无任何效果
 * <p>
 * 任务结束的方式有两种,一种以正常执行完成的方式来结束,另一种以抛出异常的方式来结束,cancel(..) 则是通过在任务执行过程中以抛出CancellationException异常的方式来结束。
 * 注意cancel(..)操作本身并不会抛出异常,它只是设置了任务的结束状态为异常结束状态。当任务的结束状态为异常结束状态时,调用和获取结果相关的api都会抛出异常,比如get()、joiner()接口等等
 * </p>
 * */
CompletableFuture<Void> task3 = CompletableFuture.runAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});
boolean cancelSuccess = task3.cancel(true);

6、在现有任务的基础上,设置对该任务结果进行处理的结果处理任务

//当前任务
CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
    return "hello,world";
});
//结果处理任务
CompletableFuture<Integer> resultHandleTask = task.handle((res, ex) -> {
    if (ex == null) {
        //如果执行成功,则打印执行结果,并返回执行结果code:0
        System.out.println("Task result is " + res);
        return 0;
    }

    //异常处理,此处选择打印调用异常栈
    ex.printStackTrace();
    //执行失败,返回code:-1
    return -1;
});

System.out.println("The result code of task is " + resultHandleTask.join());

7、设置任务的后续处理流程,其中后续处理流程会以一个新的任务存在

CompletableFuture<String> task1 = CompletableFuture.completedFuture("abc");
CompletableFuture<String> task2 = CompletableFuture.completedFuture("cde");

//设置task1执行完成后的后续执行过程
CompletableFuture<Void> nextTask1 = task1.thenRun(() -> {
    System.out.println("Done");
});
//设置task1、task2执行完成后的后续执行过程
CompletableFuture<Void> nextTask2 = task1.runAfterBoth(task2, () -> {
    System.out.println("Task1、Task2 All Done");
});
//设置task1执行完成后的后续处理流程
CompletableFuture<Void> nextTask3 = task1.thenAccept(g -> {
    System.out.println(g);
});
//设置task1、task2执行完成后的后续处理流程
CompletableFuture<Void> nextTask4 = task1.thenAcceptBoth(task2, (x, y) -> {
    System.out.println(x + y);
});
//设置task1执行完成后的后续转换流程(转换成一个新的任务)
CompletableFuture<String> nextTask5 = task1.thenApply(g -> {
    return g.toUpperCase();
});
//设置task1执行完成后的后续转换流程(转换成一个新的任务,同thenAcceptBoth(..)作用,唯一区别是任务的返回结果类型可以自定义)
CompletableFuture<String> nextTask6 = task1.thenCompose(g -> {
    return CompletableFuture.supplyAsync(() -> {
        return g.toUpperCase();
    });
});
//设置task1、task2执行完成后的后续转换流程
CompletableFuture<String> nextTask7 = task1.thenCombine(task2, (x, y) -> {
    return x + y;
});

8、选取两个并行任务中最快执行完成的任务(二选一),进行后续处理

CompletableFuture<String> task1 = CompletableFuture.completedFuture("1");
CompletableFuture<String> task2 = CompletableFuture.completedFuture("2");

CompletableFuture<Void> nextTask1 = task1.runAfterEither(task2, () -> {
    System.out.println("One of tasks done");
});

CompletableFuture<Void> nextTask2 = task1.acceptEither(task2, g -> {
    System.out.println("One of tasks done, res is " + g);
});

CompletableFuture<Integer> nextTask3 = task1.applyToEither(task2, g -> {
    return Integer.parseInt(g);
});

9、查看任务状态

CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return Integer.parseInt("99");
});
/**
 * 检测该任务是否以抛出异常的方式结束。若任务未结束,则返回false。
 * <p>
 * 此外,如果该任务通过调用cancel(..)接口以取消的方式来结束,该值也是true。
 * 因为cancel(..)的实现方式是通过以在任务中抛出CancellationException异常的方式来结束的。
 * </p>
 * */
boolean completedExceptionally = task.isCompletedExceptionally();
/***
 * 检测该任务是否已经执行结束,如果任务未结束,则返回false。如果任务已结束,则返回true,不管任务是正常结束,还是抛出异常结束
 */
boolean isDone = task.isDone();
/**
 * 检测该任务是否以取消的方式结束,如果任务未结束或者未以取消的方式结束,则返回false
 */
boolean isCancelled = task.isCancelled();

10、任务组处理

CompletableFuture<String> task1 = CompletableFuture.completedFuture("1");
CompletableFuture<String> task2 = CompletableFuture.completedFuture("2");
CompletableFuture<String> task3 = CompletableFuture.completedFuture("3");

/**
 * 任何一个任务执行完成,该任务组就完成
 * */
CompletableFuture<Object> anyTask = CompletableFuture.anyOf(task1, task2, task3);
anyTask.join();

/**
 * 所有的任务都执行完成,该任务组才会完成
 * */
CompletableFuture<Void> allTask = CompletableFuture.allOf(task1, task2, task3);
allTask.join();

 

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值