• 【JUC】1.CompletableFuture异步编程


    1. FutureTask简述

    在这里插入图片描述

    FutureTask同时实现了Runable和Future接口

    • Future是Java5新加的一个接口,它提供了一种异步并行计算的功能
    public interface Future<V> {
    
        boolean cancel(boolean mayInterruptIfRunning);
        
        boolean isDone();
    
        V get() throws InterruptedException, ExecutionException;
    
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 通过是实现Runable接口,就可以完成线程的创建

    而FutureTask既然实现了这两个接口,那么肯定会有两个接口所对应的功能

    • FutureTask的三个特点:多线程/有返回/异步任务

    2. FutureTask缺点

    • get()阻塞,非要等到结果才会离开
    • isDone()轮询,浪费无谓的CPU资源,也不见得能及时获取到计算结果

    3. CompletableFuture

    正因为有FutureTask的这些缺点,CompletableFuture才会出现

    CompletableFuture能够更好地结果这些问题

    • 在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合CompletableFuture的方法
    • 它可能代表一个明确完成的Future,也有可能代表一个完成阶段(CompletionStage),它支持在计算完成以后触发一些函数或执行某些动作
    • 它实现了Future和CompletionStage接口

    在这里插入图片描述


    4. CompletableFuture的API

    4.1 CompletableFuture的创建

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

    //runAsync方法不支持返回值
    public static CompletableFuture<Void> runAsync(Runnable runnable)
    public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
    //supplyAsync可以支持返回值
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其中带有Executor参数的方法是可以自己指定线程池的

    其中runAsync没有返回值


    4.2 获得结果和触发计算

    • get:不见不散(会抛出异常),不管计算是否计算完成都会阻塞
    • get(long timeout, TimeUnit unit):在规定时间内没有结果,则会跳过
    • getNow(T valueIfAbsent):没有计算完成的情况下,给我一个替代结果计算完,返回计算完成后的结果、没算完,返回设定的valuelfAbsent
    • join() :和get方法差不多,只是不抛出异常罢了
    • complete:主动触发计算,是否打算get方法立刻返回括号值
    public T get() throws InterruptedException, ExecutionException 
    
    public T get(long timeout, TimeUnit unit)
        
    public T getNow(T valueIfAbsent)
        
    public T join() 
    
    public boolean complete(T value) 
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.3 对计算结果进行处理

    • thenApply:计算结果存在依赖关系,两个线程串行化,只要一个线程有异常,就停
    • handle:有异常也可以往下一步走,可以根据带的异常进行判断
    public <U> CompletableFuture<U> thenApply(
        Function<? super T,? extends U> fn) {
        return uniApplyStage(null, fn);
    }
    
    public <U> CompletableFuture<U> handle(
        BiFunction<? super T, Throwable, ? extends U> fn) {
        return uniHandleStage(null, fn);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.4 对计算结果进行消费

    • thenRun:任务A执行完任务B,并且B不需要A的结果
    • thenAccept:任务A执行完执行B,B需要A的结果,但是任务B无返回值
    • thenApply:任务A执行完执行B,B需要A的结果,B有返回
    public CompletableFuture<Void> thenRun(Runnable action)
    
    public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
    
    public <U> CompletableFuture<U> thenApply(
      Function<? super T,? extends U> fn) {
      return uniApplyStage(null, fn);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    带了Async的方法表示的是:会重新在线程池中启动一个线程来执行任务


    4.5 对计算速度进行选用

    • applyToEither:谁快就用谁的结果
    • applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值
    • acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值
    • runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返回值
    public <U> CompletableFuture<U> applyToEither
    public <U> CompletableFuture<U> applyToEitherAsync
    
    public CompletableFuture<Void> acceptEither
    public CompletableFuture<Void> acceptEitherAsync
    
    public CompletableFuture<Void> runAfterEither
    public CompletableFuture<Void> runAfterEitherAsync
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.6 对计算结果进行合并

    • thenCombine:组合两个future,获取两个future的返回结果,并返回当前任务的返回值
    • thenAcceptBoth:组合两个future,获取两个future的返回结果,然后处理任务,没有返回值
    • runAfterBoth:组合两个future,不需要获取future的结果,只需要两个future处理完任务后处理该任务
    public <U,V> CompletableFuture<V> thenCombine
    public <U> CompletableFuture<Void> thenAcceptBoth
    public CompletableFuture<Void> runAfterBoth
    
    • 1
    • 2
    • 3

    4.7 多任务组合

    • allOf:等待所有任务完成
    • anyOf:只要又一个任务完成
    public static CompletableFuture<Void> allOf
    public static CompletableFuture<Object> anyOf
    
    • 1
    • 2

    4.8 回调方法

    • whenComplete:可以正常处理计算结果(带Async的话意味着这个任务是交给线程池的其他其他线程执行)
    • exceptionally:处理异常情况
    • handle:whenComplete和exceptionally的结合版
    public CompletableFuture<T> whenComplete
    public CompletableFuture<T> exceptionally
    public <U> CompletableFuture<U> handle
    
    • 1
    • 2
    • 3

    5. 函数式接口总结

    5.1 BiConsumer

    void accept(T t, U u)

    和普通消费者不一样,BiConsumer可以传入两个参数


    5.2 BiFunction

    R apply(T t, U u)

    与普通Function不同,可以传入两个参数


    5.3 BiPredication

    boolean test(T t, U u)

    和普通断言接口不一样,BiPredication可以传入两个参数


    笔记参考
    https://blog.csdn.net/TZ845195485/article/details/114692426
    https://www.yuque.com/liuyanntes/sibb9g/fhqqge

  • 相关阅读:
    001 rabbitmq减库存demo direct
    在线代码编辑器CodePen和CodeSandbox
    leetcode - 1428. Leftmost Column with at Least a One
    站在AI大模型十字路口:实地探访2023服贸会
    英国Top20名校更偏爱IB申请党?
    计算机毕业设计springboot+vue基本微信小程序的医疗监督反馈小程序 uniapp
    proxy代理服务
    工厂模式 rust和java的实现
    【MATLAB第71期】基于MATLAB的Abcboost自适应决策树多输入单输出回归预测及多分类预测模型(更新中)
    偏执的非合格公司
  • 原文地址:https://blog.csdn.net/weixin_51146329/article/details/127135289