【Java多线程-5】 CompletableFuture详解

    }

    System.out.println("执行结束!");

});



future.whenComplete(new BiConsumer<Void, Throwable>() {

    @Override

    public void accept(Void t, Throwable action) {

        System.out.println("执行完成!");

    }

});



future.exceptionally(new Function<Throwable, Void>() {

    @Override

    public Void apply(Throwable t) {

        System.out.println("执行失败:" + t.getMessage());

        return null;

    }

}).join();

}




下面一组方法虽然也返回CompletableFuture对象,但是对象的值和原来的CompletableFuture计算的值不同。当原先的CompletableFuture的值计算完成或者抛出异常的时候,会触发这个CompletableFuture对象的计算,结果由BiFunction参数计算而得。因此这组方法兼有whenComplete和转换的两个功能。



public CompletableFuture handle(BiFunction<? super T,Throwable,? extends U> fn)

public CompletableFuture handleAsync(BiFunction<? super T,Throwable,? extends U> fn)

public CompletableFuture handleAsync(BiFunction<? super T,Throwable,? extends U> fn, Executor executor)




[]( )3 结果转换

=================================================================



所谓结果转换,就是将上一段任务的执行结果作为下一阶段任务的入参参与重新计算,产生新的结果。



[]( )3.1 thenApply

------------------------------------------------------------------------



thenApply 接收一个函数作为参数,使用该函数处理上一个CompletableFuture 调用的结果,并返回一个具有处理结果的Future对象。



public CompletableFuture thenApply(Function<? super T,? extends U> fn)

public CompletableFuture thenApplyAsync(Function<? super T,? extends U> fn)

public CompletableFuture thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)




**示例:**



public static void main(String[] args) throws ExecutionException, InterruptedException {

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {

int result = 100;

System.out.println("一阶段:" + result);

    return result;

}).thenApply(number -> {

    int result = number * 3;

    System.out.println("二阶段:" + result);

    return result;

});



System.out.println("最终结果:" + future.get());

}




[]( )3.2 thenCompose

--------------------------------------------------------------------------



thenCompose 的参数为一个返回 CompletableFuture 实例的函数,该函数的参数是先前计算步骤的结果。



public CompletableFuture thenCompose(Function<? super T, ? extends CompletionStage> fn);

public CompletableFuture thenComposeAsync(Function<? super T, ? extends CompletionStage> fn) ;

public CompletableFuture thenComposeAsync(Function<? super T, ? extends CompletionStage> fn, Executor executor) ;




**示例:**



public static void main(String[] args) throws InterruptedException, ExecutionException {

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(3);

        System.out.println("第一阶段:" + number);

        return number;

    }

}).thenCompose(new Function<Integer, CompletionStage<Integer>>() {

    @Override

    public CompletionStage<Integer> apply(Integer param) {

        return CompletableFuture.supplyAsync(new Supplier<Integer>() {

            @Override

            public Integer get() {

                int number = param * 2;

                System.out.println("第二阶段:" + number);

                return number;

            }

        });

    }

});

System.out.println("最终结果: " + future.get());

}




那么 thenApply 和 thenCompose 有何区别呢:



*   thenApply 转换的是泛型中的类型,返回的是同一个CompletableFuture;

*   thenCompose 将内部的 CompletableFuture 调用展开来并使用上一个CompletableFutre 调用的结果在下一步的 CompletableFuture 调用中进行运算,是生成一个新的CompletableFuture。



下面用一个例子对对比:



public static void main(String[] args) throws InterruptedException, ExecutionException {

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");



CompletableFuture<String> result1 = future.thenApply(param -> param + " World");

CompletableFuture<String> result2 = future.thenCompose(param -> CompletableFuture.supplyAsync(() -> param + " World"));



System.out.println(result1.get());

System.out.println(result2.get());

}




[]( )4 结果消费

=================================================================



与结果处理和结果转换系列函数返回一个新的 CompletableFuture 不同,结果消费系列函数只对结果执行Action,而不返回新的计算值。



根据对结果的处理方式,结果消费函数又分为:



*   thenAccept系列:对单个结果进行消费

*   thenAcceptBoth系列:对两个结果进行消费

*   thenRun系列:不关心结果,只对结果执行Action



[]( )4.1 thenAccept

-------------------------------------------------------------------------



通过观察该系列函数的参数类型可知,它们是函数式接口Consumer,这个接口只有输入,没有返回值。



public CompletionStage thenAccept(Consumer<? super T> action);

public CompletionStage thenAcceptAsync(Consumer<? super T> action);

public CompletionStage thenAcceptAsync(Consumer<? super T> action,Executor executor);




**示例:**



public static void main(String[] args) throws ExecutionException, InterruptedException {

CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {

    int number = new Random().nextInt(10);

    System.out.println("第一阶段:" + number);

    return number;

}).thenAccept(number ->

        System.out.println("第二阶段:" + number * 5));

System.out.println("最终结果:" + future.get());

}




[]( )4.2 thenAcceptBoth

-----------------------------------------------------------------------------



thenAcceptBoth 函数的作用是,当两个 CompletionStage 都正常完成计算的时候,就会执行提供的action消费两个异步的结果。



public CompletionStage thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);

public CompletionStage thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);

public CompletionStage thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor);




**示例:**



public static void main(String[] args) throws ExecutionException, InterruptedException {

CompletableFuture<Integer> futrue1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(3) + 1;

        try {

            TimeUnit.SECONDS.sleep(number);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println("第一阶段:" + number);

        return number;

    }

});



CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(3) + 1;

        try {

            TimeUnit.SECONDS.sleep(number);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println("第二阶段:" + number);

        return number;

    }

});



futrue1.thenAcceptBoth(future2, new BiConsumer<Integer, Integer>() {

    @Override

    public void accept(Integer x, Integer y) {

        System.out.println("最终结果:" + (x + y));

    }

}).join();

}




[]( )4.3 thenRun

----------------------------------------------------------------------



thenRun 也是对线程任务结果的一种消费函数,与thenAccept不同的是,thenRun 会在上一阶段 CompletableFuture 计算完成的时候执行一个Runnable,Runnable并不使用该 CompletableFuture 计算的结果。



public CompletionStage thenRun(Runnable action);

public CompletionStage thenRunAsync(Runnable action);

public CompletionStage thenRunAsync(Runnable action,Executor executor);




**示例:**



public static void main(String[] args) throws ExecutionException, InterruptedException {

CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {

    int number = new Random().nextInt(10);

    System.out.println("第一阶段:" + number);

    return number;

}).thenRun(() ->

        System.out.println("thenRun 执行"));

System.out.println("最终结果:" + future.get());

}




[]( )5 结果组合

=================================================================



thenCombine 方法,合并两个线程任务的结果,并进一步处理。



public <U,V> CompletionStage thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);

public <U,V> CompletionStage thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);

public <U,V> CompletionStage thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);




**示例:**



public static void main(String[] args) throws ExecutionException, InterruptedException {

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(10);

        System.out.println("第一阶段:" + number);

        return number;

    }

});

CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(10);

        System.out.println("第二阶段:" + number);

        return number;

    }

});

CompletableFuture<Integer> result = future1.thenCombine(future2, new BiFunction<Integer, Integer, Integer>() {

    @Override

    public Integer apply(Integer x, Integer y) {

        return x + y;

    }

});

System.out.println("最终结果:" + result.get());

}




[]( )6 任务交互

=================================================================



所谓线程交互,是指将两个线程任务获取结果的速度相比较,按一定的规则进行下一步处理。



[]( )6.1 applyToEither

----------------------------------------------------------------------------



两个线程任务相比较,先获得执行结果的,就对该结果进行下一步的转化操作。



public CompletionStage applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);

public CompletionStage applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);

public CompletionStage applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor);




示例:



public static void main(String[] args) throws ExecutionException, InterruptedException {

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(3);

        try {

            TimeUnit.SECONDS.sleep(number);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println("第一阶段:" + number);

        return number;

    }

});

CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(3);

        try {

            TimeUnit.SECONDS.sleep(number);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println("第二阶段:" + number);

        return number;

    }

});



future1.applyToEither(future2, new Function<Integer, Integer>() {

    @Override

    public Integer apply(Integer number) {

        System.out.println("最快结果:" + number);

        return number * 2;

    }

}).join();

}




[]( )6.2 acceptEither

---------------------------------------------------------------------------



两个线程任务相比较,先获得执行结果的,就对该结果进行下一步的消费操作。



public CompletionStage acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);

public CompletionStage acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);

public CompletionStage acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor);




**示例:**



public static void main(String[] args) {

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(3) + 1;

        try {

            TimeUnit.SECONDS.sleep(number);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println("第一阶段:" + number);

        return number;

    }

});



CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

    @Override

    public Integer get() {

        int number = new Random().nextInt(3) + 1;

        try {

            TimeUnit.SECONDS.sleep(number);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println("第二阶段:" + number);

        return number;

    }

});



future1.acceptEither(future2, new Consumer<Integer>() {

    @Override

    public void accept(Integer number) {

        System.out.println("最快结果:" + number);

    }

}).join();

}




[]( )6.3 runAfterEither

-----------------------------------------------------------------------------



两个线程任务相比较,有任何一个执行完成,就进行下一步操作,不关心运行结果。



public CompletionStage runAfterEither(CompletionStage<?> other,Runnable action);

public CompletionStage runAfterEitherAsync(CompletionStage<?> other,Runnable action);

public CompletionStage runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);




示例:



import java.util.Random;

import java.util.concurrent.CompletableFuture;

import java.util.concurrent.TimeUnit;

import java.util.function.Supplier;

/**

  • @author guozhengMu

  • @version 1.0

  • @date 2019/11/7 22:44

  • @description

  • @modify

*/

public class CompletableFutureTest {

public static void main(String[] args) {

    CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

Kafka实战笔记

关于这份笔记,为了不影响大家的阅读体验,我只能在文章中展示部分的章节内容和核心截图

image.png

  • Kafka入门
  • 为什么选择Kafka
  • Karka的安装、管理和配置

image.png

  • Kafka的集群
  • 第一个Kafka程序
  • image.png

afka的生产者

image.png

  • Kafka的消费者
  • 深入理解Kafka
  • 可靠的数据传递

image.png

image.png

  • Spring和Kalka的整合
  • Sprinboot和Kafka的整合
  • Kafka实战之削峰填谷
  • 数据管道和流式处理(了解即可)

image.png

  • Kafka实战之削峰填谷

image.png

s CompletableFutureTest {

public static void main(String[] args) {

    CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {

Kafka实战笔记

关于这份笔记,为了不影响大家的阅读体验,我只能在文章中展示部分的章节内容和核心截图

[外链图片转存中…(img-8kYjdEWu-1714508453618)]

  • Kafka入门
  • 为什么选择Kafka
  • Karka的安装、管理和配置

[外链图片转存中…(img-dDgUC2PJ-1714508453618)]

  • Kafka的集群
  • 第一个Kafka程序
  • [外链图片转存中…(img-J32HpEAw-1714508453618)]

afka的生产者

[外链图片转存中…(img-LKDKIjb3-1714508453619)]

  • Kafka的消费者
  • 深入理解Kafka
  • 可靠的数据传递

[外链图片转存中…(img-0hA7fWr1-1714508453619)]

[外链图片转存中…(img-szQksoeQ-1714508453619)]

  • Spring和Kalka的整合
  • Sprinboot和Kafka的整合
  • Kafka实战之削峰填谷
  • 数据管道和流式处理(了解即可)

[外链图片转存中…(img-7otmvAel-1714508453620)]

  • Kafka实战之削峰填谷

[外链图片转存中…(img-yxfgqIth-1714508453620)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值