java高并发系列 - 第30天:JUC中工具类CompletableFuture,必备技能

总结

这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额!

某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功!

成功只会留给那些有准备的人!

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

需要这份系统化的资料的朋友,可以点击这里获取

示例代码

//无返回值

public static void runAsync() throws Exception {

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

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

}

System.out.println(“run end …”);

});

future.get();

}

//有返回值

public static void supplyAsync() throws Exception {

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

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

}

System.out.println(“run end …”);

return System.currentTimeMillis();

});

long time = future.get();

System.out.println("time = "+time);

}

计算结果完成时的回调方法

当CompletableFuture的计算结果完成,或者抛出异常的时候,可以执行特定的Action。主要是下面的方法:

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)

可以看到Action的类型是BiConsumer它可以处理正常的计算结果,或者异常情况。

whenComplete 和 whenCompleteAsync 的区别:

  • whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。

  • whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。

示例代码

public static void whenComplete() throws Exception {

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

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

}

if(new Random().nextInt()%2>=0) {

int i = 12/0;

}

System.out.println(“run end …”);

});

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;

}

});

TimeUnit.SECONDS.sleep(2);

}

thenApply 方法

当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。

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

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

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

Function

示例代码

private static void thenApply() throws Exception {

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

@Override

public Long get() {

long result = new Random().nextInt(100);

System.out.println(“result1=”+result);

return result;

}

}).thenApply(new Function<Long, Long>() {

@Override

public Long apply(Long t) {

long result = t*5;

System.out.println(“result2=”+result);

return result;

}

});

long result = future.get();

System.out.println(result);

}

第二个任务依赖第一个任务的结果。

handle 方法

handle 是执行任务完成时对结果的处理。

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

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

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

示例代码

public static void handle() throws Exception{

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

@Override

public Integer get() {

int i= 10/0;

return new Random().nextInt(10);

}

}).handle(new BiFunction<Integer, Throwable, Integer>() {

@Override

public Integer apply(Integer param, Throwable throwable) {

int result = -1;

if(throwable==null){

result = param * 2;

}else{

System.out.println(throwable.getMessage());

}

return result;

}

});

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

}

从示例中可以看出,在 handle 中可以根据任务是否有异常来进行做相应的后续处理操作。而 thenApply 方法,如果上个任务出现错误,则不会执行 thenApply 方法。

thenAccept 消费处理结果

接收任务的处理结果,并消费处理,无返回结果。

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

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

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

示例代码

public static void thenAccept() throws Exception{

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

@Override

public Integer get() {

return new Random().nextInt(10);

}

}).thenAccept(integer -> {

System.out.println(integer);

});

future.get();

}

从示例代码中可以看出,该方法只是消费执行完成的任务,并可以根据上面的任务返回的结果进行处理。并没有后续的输错操作。

thenRun 方法

跟 thenAccept 方法不一样的是,不关心任务的处理结果。只要上面的任务执行完成,就开始执行 thenAccept 。

public CompletionStage<Void> thenRun(Runnable action);

public CompletionStage<Void> thenRunAsync(Runnable action);

public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);

示例代码

public static void thenRun() throws Exception{

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

@Override

public Integer get() {

return new Random().nextInt(10);

}

}).thenRun(() -> {

System.out.println(“thenRun …”);

});

future.get();

}

该方法同 thenAccept 方法类似。不同的是上个任务处理完成后,并不会把计算的结果传给 thenRun 方法。只是处理玩任务后,执行 thenAccept 的后续操作。

thenCombine  合并任务

thenCombine 会把 两个 CompletionStage 的任务都执行完成后,把两个任务的结果一块交给 thenCombine 来处理。

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

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

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

示例代码

private static void thenCombine() throws Exception {

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

@Override

public String get() {

return “hello”;

}

});

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

@Override

public String get() {

return “hello”;

}

});

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

@Override

public String apply(String t, String u) {

return t+" "+u;

}

});

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

}

thenAcceptBoth

当两个CompletionStage都执行完成后,把结果一块交给thenAcceptBoth来进行消耗

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

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

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

示例代码

private static void thenAcceptBoth() throws Exception {

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

@Override

public Integer get() {

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

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“f1=”+t);

return t;

}

});

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

@Override

public Integer get() {

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

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“f2=”+t);

return t;

}

});

f1.thenAcceptBoth(f2, new BiConsumer<Integer, Integer>() {

@Override

public void accept(Integer t, Integer u) {

System.out.println(“f1=”+t+“;f2=”+u+“;”);

}

});

}

applyToEither 方法

两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的转化操作。

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

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

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

示例代码

private static void applyToEither() throws Exception {

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

@Override

public Integer get() {

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

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“f1=”+t);

return t;

}

});

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

@Override

public Integer get() {

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

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“f2=”+t);

return t;

}

});

CompletableFuture<Integer> result = f1.applyToEither(f2, new Function<Integer, Integer>() {

@Override

public Integer apply(Integer t) {

System.out.println(t);

return t * 2;

}

});

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

}

acceptEither 方法

两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的消耗操作。

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

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

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

示例代码

private static void acceptEither() throws Exception {

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

@Override

public Integer get() {

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

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“f1=”+t);

return t;

}

});

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

@Override

public Integer get() {

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

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

需要这份系统化的资料的朋友,可以点击这里获取

[外链图片转存中…(img-k5zG2JLn-1715455450439)]

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

[外链图片转存中…(img-WHh1UyMu-1715455450439)]

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

afka的生产者

[外链图片转存中…(img-vYzdnKsy-1715455450440)]

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

[外链图片转存中…(img-hvKsG1Gh-1715455450440)]

[外链图片转存中…(img-LCnCCvdl-1715455450440)]

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

[外链图片转存中…(img-wM6wzgPu-1715455450441)]

  • Kafka实战之削峰填谷

[外链图片转存中…(img-Hi380nMs-1715455450441)]

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

需要这份系统化的资料的朋友,可以点击这里获取

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值