JDK8-11-CompletableFuture(7)- thenApply,thenApplyAsync方法使用

JDK8-11-CompletableFuture(7)- thenApply,thenApplyAsync方法使用

thenApply 使用

回到顾客点餐,厨师炒菜打饭的例子:
1.顾客进入餐厅
2.顾客开始点餐
3.厨师按照顾客所选菜品开始炒菜
4.厨师打饭(假设没有服务员)
5.顾客开始吃饭
其中,在厨师准备饭菜的3,4步骤中,顾客处于等待状态,可以做些其他事情,比如玩手机,下面用程序模拟这个案例:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class SupplyAsyncTest06 {

    public static void main(String[] args) {
        PrintTool.printTimeAndThread("顾客进入餐厅。。。");
        PrintTool.printTimeAndThread("顾客开始点餐。。。");
        CompletableFuture<String> chefCF = CompletableFuture.supplyAsync(() -> {
            PrintTool.printTimeAndThread("厨师开始炒菜。。。");
            PrintTool.sleep(500);
            return "番茄炒蛋";
        }).thenApply(dish -> {
            PrintTool.printTimeAndThread("厨师开始盛饭。。。");
            PrintTool.sleep(100);
            return dish + "+米饭";
        });
        PrintTool.printTimeAndThread("顾客玩手机中。。。");
        try {
            PrintTool.printTimeAndThread(String.format("顾客开始吃%s", chefCF.get()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

1666405340730	|	1	|	main	|	顾客进入餐厅。。。
1666405340733	|	1	|	main	|	顾客开始点餐。。。
1666405340879	|	14	|	ForkJoinPool.commonPool-worker-1	|	厨师开始炒菜。。。
1666405340879	|	1	|	main	|	顾客玩手机中。。。
1666405341388	|	14	|	ForkJoinPool.commonPool-worker-1	|	厨师开始盛饭。。。
1666405341417	|	1	|	main	|	顾客开始吃番茄炒蛋+米饭
thenApply 与 thenCompose 区别

thenApply 表示任务执行完后再执行某个操作(任务的后置处理),与 thenCompose 类似,区别在于:

① thenApply 接收参数为 Function<? super T,? extends U> fn,函数式方法返回泛型对象U,thenCompose 接收参数为 Function<? super T, ? extends CompletionStage<U>> fn ,函数式方法返回
CompletionStage<U>

② thenApply 将方法内的操作当成上一个任务的继续,可以看成是同一个任务,所以在同一个线程执行,thenCompose 将子任务放到 ForkJoinPool.commonPool 线程池中执行,与父任务有可能处于同一线程,也可能不是同一线程

thenApplyAsync 使用

以上述例子为分析依据,将厨师打饭换成服务员A打饭:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class SupplyAsyncTest07 {

    public static void main(String[] args) {
        PrintTool.printTimeAndThread("顾客进入餐厅。。。");
        PrintTool.printTimeAndThread("顾客开始点餐。。。");
        CompletableFuture<String> chefCF = CompletableFuture.supplyAsync(() -> {
            PrintTool.printTimeAndThread("厨师开始炒菜。。。");
            PrintTool.sleep(500);
            return "番茄炒蛋";
        }).thenApplyAsync(dish -> {
            PrintTool.printTimeAndThread("服务员A开始盛饭。。。");
            PrintTool.sleep(100);
            return dish + "+米饭";
        });
        PrintTool.printTimeAndThread("顾客玩手机中。。。");
        try {
            PrintTool.printTimeAndThread(String.format("顾客开始吃%s", chefCF.get()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

执行结果如下:

1666498382154	|	1	|	main	|	顾客进入餐厅。。。
1666498382154	|	1	|	main	|	顾客开始点餐。。。
1666498382295	|	14	|	ForkJoinPool.commonPool-worker-1	|	厨师开始炒菜。。。
1666498382295	|	1	|	main	|	顾客玩手机中。。。
1666498382802	|	14	|	ForkJoinPool.commonPool-worker-1	|	服务员A开始盛饭。。。
1666498382939	|	1	|	main	|	顾客开始吃番茄炒蛋+米饭

thenApplyAsync 会将函数式方法中的操作放到一个新的任务中执行,也就是 服务员A盛饭会在一个新的任务中执行,但是上述例子厨师炒菜和服务员打饭都是由 ForkJoinPool.commonPool-worker-1 线程执行的,原因在于,thenApplyAsync 会等待调用任务执行完再执行本方法内的操作,也就是 服务员A开始盛饭时,厨师已经炒完菜了,所以 ForkJoinPool.commonPool-worker-1 处于空闲状态,虽然 服务员A打饭是一个新的任务,但是都是由 ForkJoinPool.commonPool 线程池分配线程执行,所以有可能被处于空闲状态的 ForkJoinPool.commonPool-worker-1 执行,这里要将任务与线程的概念区分开

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值