CompletableFuture异步编排(1)

1.业务场景

查询商品详情页的逻辑比较复杂,有些数据还需要远程调用,必然需要花费更多的时间
在这里插入图片描述
假如商品详情页的每个查询,需要如下标注的时间才能完成
那么,用户需要 5.5s 后才能看到商品详情页的内容。很显然是不能接受的。
如果有多个线程同时完成这 6 步操作,也许只需要 1.5s 即可完成响应

2.什么是CompletableFuture

在jdk8中CompletableFuture属于Future 接口的实现类,可以获取线程的执行结果(idea中ctrl+alt+shift+u可以查看继承图),类似于Node.js中的Promise
在这里插入图片描述
在这里插入图片描述

3.创建异步对象

CompletableFuture 提供了4个静态方法来创建一个异步操作

  • runXxxx 都是没有返回结果的,supplyXxx 都是可以获取返回结果的
  • 可以传入自定义的线程池,否则就用默认的线程池
public static CompletableFuture<Void> runAsync(Runnable runnable)public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

代码示例

package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * 异步编排CompletableFuture(创建异步对象)
 * @author zfh
 * @email hst1406959716@163.com
 * @date 2022-01-04 09:40:46
 */
public class CompletableFutureDemo {
    public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            5,200,10,
            TimeUnit.SECONDS,new LinkedBlockingDeque<>(10000),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main......start.....");

        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
        },threadPoolExecutor);
    
        System.out.println("main......end......." );
    }
}

在这里插入图片描述

package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * 异步编排CompletableFuture(创建异步对象)
 * @author zfh
 * @email hst1406959716@163.com
 * @date 2022-01-04 09:40:46
 */
public class CompletableFutureDemo {
    public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            5,200,10,
            TimeUnit.SECONDS,new LinkedBlockingDeque<>(10000),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main......start.....");

        CompletableFuture.supplyAsync(()->{
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        },threadPoolExecutor);
    
        System.out.println("main......end......." );
    }
}

在这里插入图片描述
可以获取返回结果

package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * 异步编排CompletableFuture(创建异步对象)
 * @author zfh
 * @email hst1406959716@163.com
 * @date 2022-01-04 09:40:46
 */
public class CompletableFutureDemo {
    public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            5,200,10,
            TimeUnit.SECONDS,new LinkedBlockingDeque<>(10000),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main......start.....");

//        CompletableFuture.supplyAsync(()->{
//            System.out.println("当前线程:" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果:" + i);
//            return i;
//        },threadPoolExecutor);
        //也可获取返回值
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, threadPoolExecutor);

        Integer integer = integerCompletableFuture.get();
        System.out.println("main......end......." + integer);
    }
}

在这里插入图片描述

4.计算完成时回调方法

public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action)public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action)public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor)public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)
  • a.whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况
  • b.whenComplete 和 whenCompleteAsync 的区别:
    whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
    whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。
  • c.方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * 异步编排CompletableFuture(计算完成时回调方法)
 * @author zfh
 * @email hst1406959716@163.com
 * @date 2022-01-04 09:48:36
 */
public class CompletableFutureDemo2 {
    public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            5,100,10,
            TimeUnit.SECONDS,new LinkedBlockingDeque<>(1000),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main......start.....");

        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, threadPoolExecutor).whenComplete((res,exceptiom)->{
            //能感知异常,但不能修改返回数据
            System.out.println("异步任务成功完成啦....结果是:" + res + ";异常是:" + exceptiom);
        });

        System.out.println("main......end......." );
    }
}

在这里插入图片描述
改成10/0
在这里插入图片描述
使用exceptionally

package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * 异步编排CompletableFuture(计算完成时回调方法)
 * @author zfh
 * @email hst1406959716@163.com
 * @date 2022-01-04 09:48:36
 */
public class CompletableFutureDemo2 {
    public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            5,100,10,
            TimeUnit.SECONDS,new LinkedBlockingDeque<>(1000),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main......start.....");

        /**
         * 方法完成后的感知
         */
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果:" + i);
            return i;
        }, threadPoolExecutor).whenComplete((res,exceptiom)->{
            //能感知异常,但不能修改返回数据
            System.out.println("异步任务成功完成啦....结果是:" + res + ";异常是:" + exceptiom);
        }).exceptionally(throwable -> {
            //能感知异常,能修改返回数据(作为默认值)
            return 10;
        });
        
        Integer integer = integerCompletableFuture.get();
        System.out.println("main......end......." + integer);
    }
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值