JAVA8 CompletableFuture 异步编排 异步回调 案例实现 源码解析

JUC CompletableFuture 异步编排

使用场景:

​ 当业务逻辑复杂时,特别是在微服务下,有些数据还需要远程调用.多个业务逻辑独立运行将耗费更多的时间.

例如:

  • 查询商品基本信息 -> 0.5s
  • 查询商品库存信息(远程调用) -> 1s
  • 查询商品图片 -> 0.5s
  • 查询商品规格属性 (依赖商品基本信息查询结果) -> 0.5s
  • 提交所有商品信息 (依赖其他查询结果) -> 1s

所有应用使用单线程顺序执行时将需要2.5s才能完成.如果有多个线程同时操作(需要注意数据的依赖性),也许只需要2.5s.

使用CompletableFuture 异步编排实现场景:

  • 分析各个异步任务之间的数据依赖
  • 分析各个异步任务是否有返回值
public class CompletableFutureDemo {
   
    //自定义线程池
    private static ExecutorService service = new ThreadPoolExecutor(5,
                                                                    10,
                                                                    30,
                                                                    TimeUnit.SECONDS,
                                                                    new LinkedBlockingDeque<Runnable>(3),
                                                                    Executors.defaultThreadFactory(),
                                                                    new ThreadPoolExecutor.AbortPolicy());
    public  static void main(String args[]){
   
        //三个没有数据依赖的可并行线程
        CompletableFuture<String> futureBasic = CompletableFuture.supplyAsync(() -> {
   
            System.out.println("商品基本信息对象查询完成");
            return "商品基本信息对象";
        }, service);
        CompletableFuture<String> futureWare = CompletableFuture.supplyAsync(() -> {
   
            //TODO 远程调用库存服务模块
            System.out.println("商品库存对象查询完成");
            return "商品库存对象";
        }, service);
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
   
            System.out.println("商品图片对象查询完成");
            return "商品图片对象";
        }, service);

        //线程串行化方法 查询商品规格属性   (依赖商品基本信息查询结果)
        CompletableFuture<String> futureInfo = futureBasic.thenApplyAsync((basicResult) -> {
   
            //从basicResult 中获取商品基本信息  查询商品规格属性
            System.out.println("商品规格属性对象查询完成");
            return "商品规格属性对象";
        }, service);

        //当4个商品对象的信息查询线程全部结束后,开启提交所有商品信息线程
        CompletableFuture<Void> futureFinish = CompletableFuture.allOf(futureBasic, futureWare, futureImg, futureInfo);


        try {
   
            //等待所有线程结束
            futureFinish.get();
            CompletableFuture<Void> futureCommit = CompletableFuture.runAsync(() -> {
   
                System.out.println("商品提交");
            }, service);

            //调用对应CompletableFuture.get方法获取返回值
            System.out.println(futureBasic.get());
            System.out.println(futureWare.get());
            System.out.println(futureImg.get());
            System.out.println(futureInfo.get());

        }catch(Exception e) {
   
            e.printStackTrace();
        }

    }
}

运行结果:

商品基本信息对象查询完成
商品库存对象查询完成
商品图片对象查询完成
商品规格属性对象查询完成
商品基本信息对象
商品库存对象
商品图片对象
商品规格属性对象
商品提交

1. 创建异步对象

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

  • runAsync 传入Runnable接口参数,不产生返回值
  • supplyAsync 传入Supplier供给型接口参数,产生一个返回值
  • 两个方法均可以传入自定义的线程池对象 Executor
    java8 四大函数式接口

源码解析:

Executor参数接受一个线程池对象:

public interface ExecutorService extends Executor {
   

Supplier是一个供给型函数式接口:

@FunctionalInterface
public interface Supplier<T> {
   
    /**
     * Gets a result.
     * @return a result
     */
    T get();
}

runAsync 不产生返回值

public static CompletableFuture<Void> runAsync(Runnable runnable) {
   
    return asyncRunStage(asyncPool, runnable);
}
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor) {
   
    return asyncRunStage(screenExecutor(executor), runnable);
}

supplyAsync 产生一个返回值

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
   
    return asyncSupplyStage(asyncPool, supplier);
}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor) {
   
    return asyncSupplyStage(screenExecutor(executor), supplier);
}

测试:

1. runAsync(Runnable,Executor):

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletableFutureDemo {
   
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
   
        System.out.println("main start ....");
        //runAsync
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
   
            System.out.println(Thread.currentThread().getName());
            int i = 5;
            System.out.println(i);
        }, executor);
        System.out.println("main end ....");
    }

}

输出:

main start ....
main end ....
pool-1-thread-1
5

2. supplyAsync(Supplier supplier,Executor executor):

package com.rwp.gulimail.search.thread;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

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

public class CompletableFutureDemo {
   
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值