这一类方法都由上一阶段(或者两个阶段,或者两个阶段中的任意一个)的正常完成结果触发,然后以该结果执行给定的函数,产出新的结果。这里把异步执行的两者形式也列举出来了。
//依赖单个阶段
public CompletionStage thenApply(Function super T,? extends U> fn); // 默认执行方式
public CompletionStage thenApplyAsync(Function super T,? extends U> fn);// 默认的异步执行方式
public CompletionStage thenApplyAsync(Function super T,? extends U> fn,Executor executor); //自定义的执行方式
//依赖两个阶段都完成
public CompletionStage thenCombine(CompletionStage extends U> other, BiFunction super T,? super U,? extends V> fn);
public CompletionStage thenCombineAsync(CompletionStage extends U> other, BiFunction super T,? super U,? extends V> fn);
public CompletionStage thenCombineAsync(CompletionStage extends U> other, BiFunction super T,? super U,? extends V> fn, Executor executor);
//依赖两个阶段中的任何一个完成
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);
代码如下:
Person类
package com.redisson;
/**
* @Description TODO
* @Date 2020/7/28 13:41
* @Author zsj
*/
public class Person {
public int age;
public String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试类如下:
package com.redisson;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
/**
* @Description TODO
* @Date 2020/7/28 9:09
* @Author zsj
*/
public class MainFour {
public static void main(String[] args) throws Exception {
// thenCombineAsync();
// thenApplyAsync();
applyToEitherAsync();
Thread.sleep(10000);
}
public static void thenCombineAsync() {
CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Person p = new Person();
p.setAge(10);
p.setName("p1");
return p;
}
});
CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Person p = new Person();
p.setAge(20);
p.setName("p2");
return p;
}
});
CompletableFuture three = one.thenCombineAsync(two, (p1, p2) -> {
Person p3 = new Person();
p3.setAge(p1.getAge());
p3.setName(p2.getName());
return p3;
});
three.thenAcceptAsync((person) -> {
System.out.println(person.getAge());
System.out.println(person.getName());
}).exceptionally((ee) -> {
ee.printStackTrace();
return null;
});
}
public static void thenApplyAsync() {
CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Person p = new Person();
p.setAge(10);
p.setName("p1");
return p;
}
});
CompletableFuture two = one.thenApplyAsync((p1) -> {
Person p2 = new Person();
p2.setAge(p1.getAge() + 11);
p2.setName("p2");
return p2;
});
two.thenAcceptAsync((person) -> {
System.out.println(person.getAge());
System.out.println(person.getName());
}).exceptionally((ee) -> {
ee.printStackTrace();
return null;
});
}
public static void applyToEitherAsync() {
CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Person p = new Person();
p.setAge(10);
p.setName("p1");
return p;
}
});
CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Person p = new Person();
p.setAge(20);
p.setName("p2");
return p;
}
});
CompletableFuture three = one.applyToEitherAsync(two, (person) -> {
Person p3 = new Person();
p3.setAge(person.getAge());
p3.setName(person.getName());
return p3;
});
three.thenAcceptAsync((person) -> {
System.out.println(person.getAge());
System.out.println(person.getName());
}).exceptionally((ee) -> {
ee.printStackTrace();
return null;
});
}
}
这一类方法都由上一阶段(或者两个阶段,或者两个阶段中的任意一个)正常完成的结果触发,然后以该结果执行给定的操作action,但不会对阶段的结果进行影响。这里把异步执行的两者形式也列举出来了。
//依赖单个阶段
public CompletionStage thenAccept(Consumer super T> action);
public CompletionStage thenAcceptAsync(Consumer super T> action);
public CompletionStage thenAcceptAsync(Consumer super T> action, Executor executor);
//依赖两个阶段都完成
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 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);
测试类如下:
package com.redisson;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
/**
* @Description TODO
* @Date 2020/7/17 15:18
* @Author zsj
*/
public class MainFive {
public static void main(String[] args) throws Exception {
// thenAccept();
// thenAcceptBoth();
acceptEither();
// 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
Thread.sleep(10000);
}
public static void thenAccept() {
CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p1");
person.setAge(10);
return person;
}
}).thenAcceptAsync((person) -> {
System.out.println("age====" + person.getAge());
});
}
public static void thenAcceptBoth() {
CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p1");
person.setAge(10);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return person;
}
});
CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p2");
person.setAge(20);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return person;
}
});
CompletableFuture three = one.thenAcceptBothAsync(two, (s1, s2) -> System.out.println(s1.getAge() + " " + s2.getName()));
}
public static void acceptEither() {
CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p1");
person.setAge(10);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return person;
}
});
CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p2");
person.setAge(20);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return person;
}
});
one.acceptEitherAsync(two, person -> {
System.out.println(person.getAge());
});
}
}
这一类方法只要求上一阶段(或者两个阶段,或者两个阶段中的任意一个)正常完成,并不关心其具体结果,从而执行指定的操作cation,但不会对阶段的结果进行影响。这里把异步执行的两者形式也列举出来了。
//依赖单个阶段
public CompletionStage thenRun(Runnable action);
public CompletionStage thenRunAsync(Runnable action);
public CompletionStage thenRunAsync(Runnable action, Executor executor);
//依赖两个阶段都完成
public CompletionStage runAfterBoth(CompletionStage> other, Runnable action);
public CompletionStage runAfterBothAsync(CompletionStage> other, Runnable action);
public CompletionStage runAfterBothAsync(CompletionStage> other, Runnable action, Executor executor);
//依赖两个阶段中的任何一个完成
public CompletionStage runAfterEither(CompletionStage> other, Runnable action);
public CompletionStage runAfterEitherAsync(CompletionStage> other, Runnable action);
public CompletionStage runAfterEitherAsync(CompletionStage> other, Runnable action, Executor executor);
代码如下:
package com.redisson;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
/**
* @Description TODO
* @Date 2020/7/28 15:14
* @Author zsj
*/
public class MainSix {
public static void main(String[] args) throws Exception {
// thenRun();
// runAfterBoth();
runAfterEither();
// 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
Thread.sleep(10000);
}
public static void thenRun() {
CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Person p = new Person();
p.setAge(10);
p.setName("p1");
return p;
}
});
one.thenRun(() -> System.out.println("hello world"));
}
public static void runAfterBoth() {
//不关心这两个CompletionStage的结果,只关心这两个CompletionStage正常执行完毕,之后在进行操作(Runnable)。
CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p1");
person.setAge(10);
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return person;
}
});
CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p2");
person.setAge(20);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return person;
}
});
one.runAfterBoth(two, () -> System.out.println("hello world"));
}
public static void runAfterEither() {
//不关心这两个CompletionStage的结果,只关心这两个CompletionStage正常执行完毕,之后在进行操作(Runnable)。
CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p1");
person.setAge(10);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return person;
}
});
CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
@Override
public Person get() {
Person person = new Person();
person.setName("p2");
person.setAge(20);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return person;
}
});
one.runAfterEither(two, () -> System.out.println("hello world"));
}
}
public CompletionStage thenCompose(Function super T, ? extends CompletionStage> fn);
public CompletionStage thenComposeAsync(Function super T, ? extends CompletionStage> fn);
public CompletionStage thenComposeAsync(Function super T, ? extends CompletionStage> fn, Executor executor);
public CompletionStage whenComplete(BiConsumer super T, ? super Throwable> action);
public CompletionStage whenCompleteAsync(BiConsumer super T, ? super Throwable> action);
public CompletionStage whenCompleteAsync(BiConsumer super T, ? super Throwable> action, Executor executor);
上面的一、二、三、四种类型的方法都需要依赖的阶段正常完成,如果异常完成将导致上面介绍的四种类型的方法最终也异常完成,不会得出我们希望的结果。而whenComplete则不论依赖的上一个阶段是正常完成还是异常完成都不会影响它的执行,但它是一个消耗型接口,即不会对阶段的原来结果产生影响,结合thenCombine综合whenComplete的示例如下:
@Test
public void thenCombine(){
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (1 == 1) {
throw new RuntimeException("测试一下异常情况");
}
return "hello ";
}).thenCombine(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("return world..."); //会执行
return "world";
}), (s1, s2) -> {
String s = s1 + " " + s2; //并不会执行
System.out.println("combine result :"+s); //并不会执行
return s;
}).whenComplete((s, t) -> {
System.out.println("current result is :" +s);
if(t != null){
System.out.println("阶段执行过程中存在异常:");
t.printStackTrace();
}
}).join();
System.out.println("final result:"+result); //并不会执行
}
whenComplete是对不论依赖阶段正常完成还是异常完成时的消耗或者消费,即不会改变阶段的现状,而handle前缀的方法则是对应的产出型方法,即可以对正常完成的结果进行转换,也可以对异常完成的进行补偿一个结果,即可以改变阶段的现状。
public CompletionStage handle (BiFunction super T, Throwable, ? extends U> fn);
public CompletionStage handleAsync(BiFunction super T, Throwable, ? extends U> fn);
public CompletionStage handleAsync(BiFunction super T, Throwable, ? extends U> fn, Executor executor);
@Test
public void handle() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//出现异常
if (1 == 3) {
throw new RuntimeException("测试一下异常情况");
}
return "Tom";
}).handle((s, t) -> {
if (t != null) { //出现异常了
return "John";
}
return s; //这里也可以对正常结果进行转换
}).join();
System.out.println(result);
}
handle的第一个参数s是上一个阶段的结果,t参数是Throwable类型的异常,这里上一个阶段如果没有抛出异常,那么最终打印的结果是"Tom",现在通过handle对出现异常的情况进行了补偿返回John,所以上例最终其实打印的是"John"。
第五、六两种类型的方法是对于不论依赖的阶段是正常完成还是异常完成的处理,CompletionStage还提供了一个仅当上一个阶段异常完成时的处理,并且可以修改阶段的结果:
public CompletionStage exceptionally(Function fn);
@Test
public void exceptionally() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (1 == 1) {
throw new RuntimeException("测试一下异常情况");
}
return "s1";
}).exceptionally(e -> {
e.printStackTrace(); //e肯定不会null
return "hello world"; //补偿返回
}).join();
System.out.println(result); //打印hello world
}
可见exceptionally只有一个参数e,表示上一个节点的异常,只有上一个阶段异常完成才会被执行,以上示例在异常时返回了新的值"hello world"对出现异常的阶段进行了补偿,所以最终整个阶段不会出现异常,并打印出"hello world"。
public CompletableFuture toCompletableFuture();
返回一个与此阶段保持相同完成属性的CompletableFuture实例。如果此阶段已经是一个CompletableFuture,那么直接返回该阶段本身,否则此方法的调用可能等效于thenApply(x -> x),但返回一个类型为CompletableFuture的实例。不选择实现该互操作性的CompletionStage实现,可能会抛出UnsupportedOperationException异常