java then_Java8新的异步编程方式 CompletableFuture(二)

本文详细介绍了Java8中CompletableFuture的特性,包括map、flatMap、thenCombine、thenAcceptBoth等方法的使用,以及如何在异步编程中进行数据转换和组合。通过实例展示了如何利用CompletableFuture进行异步操作和结果处理。
摘要由CSDN通过智能技术生成

上一篇文章,讲述了Future模式的机制、缺点,CompletableFuture产生的由来、静态工厂方法、complete()方法等等。

本文将继续整理CompletableFuture的特性。

3.3 转换

我们可以通过CompletableFuture来异步获取一组数据,并对数据进行一些转换,类似RxJava、Scala的map、flatMap操作。

3.3.1 map

方法名

描述

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

接受一个Function super T,? extends U>参数用来转换CompletableFuture

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

接受一个Function super T,? extends U>参数用来转换CompletableFuture,使用ForkJoinPool

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

接受一个Function super T,? extends U>参数用来转换CompletableFuture,使用指定的线程池

thenApply的功能相当于将CompletableFuture转换成CompletableFuture

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

future = future.thenApply(new Function() {

@Override

public String apply(String s) {

return s + " World";

}

}).thenApply(new Function() {

@Override

public String apply(String s) {

return s.toUpperCase();

}

});

try {

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

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

再用lambda表达式简化一下

CompletableFuture future = CompletableFuture.supplyAsync(() -> "Hello")

.thenApply(s -> s + " World").thenApply(String::toUpperCase);

try {

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

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

执行结果:

HELLO WORLD

下面的例子,展示了数据流的类型经历了如下的转换:String -> Integer -> Double。

CompletableFuture future = CompletableFuture.supplyAsync(() -> "10")

.thenApply(Integer::parseInt)

.thenApply(i->i*10.0);

try {

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

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

执行结果:

100.0

3.3.2 flatMap

方法名

描述

thenCompose(Function super T, ? extends CompletionStage> fn)

在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。

thenComposeAsync(Function super T, ? extends CompletionStage> fn)

在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。使用ForkJoinPool。

thenComposeAsync(Function super T, ? extends CompletionStage> fn,Executor executor)

在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。使用指定的线程池。

thenCompose可以用于组合多个CompletableFuture,将前一个结果作为下一个计算的参数,它们之间存在着先后顺序。

CompletableFuture future = CompletableFuture.supplyAsync(() -> "Hello")

.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));

try {

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

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

执行结果:

Hello World

下面的例子展示了多次调用thenCompose()

CompletableFuture future = CompletableFuture.supplyAsync(() -> "100")

.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + "100"))

.thenCompose(s -> CompletableFuture.supplyAsync(() -> Double.parseDouble(s)));

try {

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

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

执行结果:

100100.0

3.4 组合

方法名

描述

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

当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。

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

当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。使用ForkJoinPool。

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

当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。使用指定的线程池。

现在有CompletableFuture、CompletableFuture和一个函数(T,U)->V,thenCompose就是将CompletableFuture和CompletableFuture变为CompletableFuture。

CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "100");

CompletableFuture future2 = CompletableFuture.supplyAsync(() -> 100);

CompletableFuture future = future1.thenCombine(future2, (s, i) -> Double.parseDouble(s + i));

try {

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

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

执行结果:

100100.0

使用thenCombine()之后future1、future2之间是并行执行的,最后再将结果汇总。这一点跟thenCompose()不同。

thenAcceptBoth跟thenCombine类似,但是返回CompletableFuture类型。

方法名

描述

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

当两个CompletableFuture都正常完成后,执行提供的action,用它来组合另外一个CompletableFuture的结果。

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

当两个CompletableFuture都正常完成后,执行提供的action,用它来组合另外一个CompletableFuture的结果。使用ForkJoinPool。

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

当两个CompletableFuture都正常完成后,执行提供的action,用它来组合另外一个CompletableFuture的结果。使用指定的线程池。

CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "100");

CompletableFuture future2 = CompletableFuture.supplyAsync(() -> 100);

CompletableFuture future = future1.thenAcceptBoth(future2, (s, i) -> System.out.println(Double.parseDouble(s + i)));

try {

future.get();

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

执行结果:

100100.0

3.5 计算结果完成时的处理

当CompletableFuture完成计算结果后,我们可能需要对结果进行一些处理。

3.5.1 执行特定的Action

方法名

描述

whenComplete(BiConsumer super T,? super Throwable> action)

当CompletableFuture完成计算结果时对结果进行处理,或者当CompletableFuture产生异常的时候对异常进行处理。

whenCompleteAsync(BiConsumer super T,? super Throwable> action)

当CompletableFuture完成计算结果时对结果进行处理,或者当CompletableFuture产生异常的时候对异常进行处理。使用ForkJoinPool。

whenCompleteAsync(BiConsumer super T,? super Throwable> action, Executor executor)

当CompletableFuture完成计算结果时对结果进行处理,或者当CompletableFuture产生异常的时候对异常进行处理。使用指定的线程池。

CompletableFuture.supplyAsync(() -> "Hello")

.thenApply(s->s+" World")

.thenApply(s->s+ "\nThis is CompletableFuture demo")

.thenApply(String::toLowerCase)

.whenComplete((result, throwable) -> System.out.println(result));

执行结果:

hello world

this is completablefuture demo

3.5.2 执行完Action可以做转换

方法名

描述

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

当CompletableFuture完成计算结果或者抛出异常的时候,执行提供的fn

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

当CompletableFuture完成计算结果或者抛出异常的时候,执行提供的fn,使用ForkJoinPool。

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

当CompletableFuture完成计算结果或者抛出异常的时候,执行提供的fn,使用指定的线程池。

CompletableFuture future = CompletableFuture.supplyAsync(() -> "100")

.thenApply(s->s+"100")

.handle((s, t) -> s != null ? Double.parseDouble(s) : 0);

try {

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

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

执行结果:

100100.0

在这里,handle()的参数是BiFunction,apply()方法返回R,相当于转换的操作。

@FunctionalInterface

public interface BiFunction {

/**

* Applies this function to the given arguments.

*

* @param t the first function argument

* @param u the second function argument

* @return the function result

*/

R apply(T t, U u);

/**

* Returns a composed function that first applies this function to

* its input, and then applies the {@code after} function to the result.

* If evaluation of either function throws an exception, it is relayed to

* the caller of the composed function.

*

* @param the type of output of the {@code after} function, and of the

* composed function

* @param after the function to apply after this function is applied

* @return a composed function that first applies this function and then

* applies the {@code after} function

* @throws NullPointerException if after is null

*/

default BiFunction andThen(Function super R, ? extends V> after) {

Objects.requireNonNull(after);

return (T t, U u) -> after.apply(apply(t, u));

}

}

而whenComplete()的参数是BiConsumer,accept()方法返回void。

@FunctionalInterface

public interface BiConsumer {

/**

* Performs this operation on the given arguments.

*

* @param t the first input argument

* @param u the second input argument

*/

void accept(T t, U u);

/**

* Returns a composed {@code BiConsumer} that performs, in sequence, this

* operation followed by the {@code after} operation. If performing either

* operation throws an exception, it is relayed to the caller of the

* composed operation. If performing this operation throws an exception,

* the {@code after} operation will not be performed.

*

* @param after the operation to perform after this operation

* @return a composed {@code BiConsumer} that performs in sequence this

* operation followed by the {@code after} operation

* @throws NullPointerException if {@code after} is null

*/

default BiConsumer andThen(BiConsumer super T, ? super U> after) {

Objects.requireNonNull(after);

return (l, r) -> {

accept(l, r);

after.accept(l, r);

};

}

}

所以,handle()相当于whenComplete()+转换。

3.5.3 纯消费(执行Action)

方法名

描述

thenAccept(Consumer super T> action)

当CompletableFuture完成计算结果,只对结果执行Action,而不返回新的计算值

thenAcceptAsync(Consumer super T> action)

当CompletableFuture完成计算结果,只对结果执行Action,而不返回新的计算值,使用ForkJoinPool。

thenAcceptAsync(Consumer super T> action, Executor executor)

当CompletableFuture完成计算结果,只对结果执行Action,而不返回新的计算值

thenAccept()是只会对计算结果进行消费而不会返回任何结果的方法。

CompletableFuture.supplyAsync(() -> "Hello")

.thenApply(s->s+" World")

.thenApply(s->s+ "\nThis is CompletableFuture demo")

.thenApply(String::toLowerCase)

.thenAccept(System.out::print);

执行结果:

hello world

this is completablefuture demo

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值