简介
CompletableFuture能够将回调放到与任务不同的线程中执行,也能将回调作为继续执行的同步函数,在与任务相同的线程中执行。它避免了传统回调最大的问题,那就是能够将控制流分离到不同的事件处理器中。
CompletableFuture弥补了Future模式的缺点。在异步的任务完成后,需要用其结果继续操作时,无需等待。可以直接通过thenAccept、thenApply、thenCompose等方式将前面异步处理的结果交给另外一个异步事件处理线程来处理。
supplyAsync和runAsync 两者的区别是 runAsync没有返回值 supplyAsync有返回值
allOf
通过join等待指定的线程完成。
public static List<String> testRun(){
List<String> list = new ArrayList<>();
Instant start = Instant.now();
CompletableFuture<Void> test1 = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(3000);
list.add("a");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
CompletableFuture<Void> test2 = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(10000);
list.add("b");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
CompletableFuture<Void> test3 = CompletableFuture.runAsync(() -> {
list.add("c");
});
//保证三个线程都完成!
CompletableFuture.allOf(test1,test2,test3).join();
Instant end = Instant.now();
System.out.println("程序总耗时"+Duration.between(start, end).toMillis());
System.out.println(list.toString());
return list;
}
result:
complete
complete(T t)方法,完成异步执行,并返回future的结果
* future.get()在等待执行结果时,程序会一直block,如果此时调用complete(T t)会立即执行
* 注意::1 complete的调用至能一次 2 如果future已经执行完毕能够返回结果,此时再调用complete(T t)则会无效
demo
public static void testSupplyAsync() throws Exception {
Instant start = Instant.now();
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
return "hello";
} catch (InterruptedException e) {
throw new RuntimeException();
}
});
future.complete("word");
//获取返回值
String s = future.get();
Instant end = Instant.now();
System.out.println(s);
System.out.println("程序总耗时"+Duration.between(start, end).toMillis());
}
result
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);
功能:当前任务正常完成以后执行,当前任务的执行结果可以作为下一任务的输入参数,无返回值.
场景:任务a执行完成后将结果传入任务b执行,任务b无返回值
/**
* 用于消费上一个任务的消费结果 无返回值
* */
public static void testThenAccept() throws Exception{
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
return 1;
}).thenAccept((b) -> {
System.out.println(b);
});
}
thenRun(…)
public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
功能:对不关心上一步的计算结果,执行下一个操作
场景:执行任务A,任务A执行完以后,执行任务B,任务B不接受任务A的返回值(不管A有没有返回值),也无返回值
demo
/**
* 对不关心上一步的计算结果,执行下一个操作 无返回值
* */
public static void testThenRun(){
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
System.out.println("我是第一个任务");
} catch (Exception e) {
e.printStackTrace();
}
}).thenRunAsync(() -> {
System.out.println("我执行了");
});
}
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)
功能:当前任务正常完成以后执行,当前任务的执行的结果会作为下一任务的输入参数,有返回值
场景:多个任务串联执行,下一个任务的执行依赖上一个任务的结果,每个任务都有输入和输出
实例1:异步执行任务A,当任务A完成时使用A的返回结果resultA作为入参进行任务B的处理,可实现任意多个任务的串联执行
/**
* 当前任务正常完成以后执行,当前任务的执行的结果会作为下一任务的输入参数,有返回值
* */
public static void testThenApply() throws Exception{
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
System.out.println("我是第一个任务");
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}).thenApply((b) -> {
return b + 1;
}).thenApply((c) -> {
return c + 1;
});
future.join(); //future.join()先得到任务A的返回值,然后再拿返回值做入参去执行任务B
Integer integer = future.get();
}
thenCombine
public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor)
功能:将两个任务合并
demo:
/**
* 将两个任务的返回值结合起来
* */
public static void testThenCombiney() throws Exception{
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10000);
System.out.println("我是第一个任务");
} catch (Exception e) {
e.printStackTrace();
}
return 1;
});
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
System.out.println("我是第一个任务");
} catch (Exception e) {
e.printStackTrace();
}
return 2;
});
CompletableFuture<Integer> future3 = future1.thenCombine(future2, (a, b) -> {
return a + b;
});
Integer integer = future3.get();
System.out.println(integer);
}
public static void testThenCombineyTwo() throws Exception{
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}).thenCombine(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
return 2;
}), (s1, s2) -> s1 + " " + s2);
System.out.println(future.get());
}
runAfterBoth
不关心这两个任务的结果,只关心这两个任务执行完毕,之后在进行操作(Runnable)。
demo:
public static void testRunAfterBothAsync(){
Instant start = Instant.now();
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}).runAfterBoth(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
return 2;
}), () -> System.out.println("任务执行完毕"));
future.join();
Instant end = Instant.now();
System.out.println("程序总耗时"+Duration.between(start, end).toMillis());
}
applyToEither
两个任务,谁计算的快,我就用那个任务的结果进行下一步的转化操作
demo:
public static void testApplyToEither() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).applyToEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello world";
}), s -> s).join();
System.out.println(result);
}
runAfterEither
两个任务,任何一个完成了都会执行下一步的操作(Runnable)。
demo:
/**
*
* 两个任务,任何一个完成了都会执行下一步的操作(Runnable)。
* */
public static void runAfterEither() throws Exception{
Instant start = Instant.now();
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).runAfterEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s2";
}), () -> System.out.println("hello world"));
future.join();
Instant end = Instant.now();
System.out.println("程序总耗时"+Duration.between(start, end).toMillis());
}
exceptionally
功能:当运行出现异常时,调用该方法可进行一些补偿操作,如设置默认值.
场景:异步执行任务A获取结果,如果任务A执行过程中抛出异常,则使用默认值100返回.
/**
* 当运行时出现了异常,可以通过exceptionally进行补偿。
* */
public static void TestExceptionally() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (1 == 1) {
throw new RuntimeException("测试一下异常情况");
}
return "s1";
}).exceptionally(e -> {
System.out.println(e.getMessage());
return "hello world";
}).join();
System.out.println(result);
}
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 void handle() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//出现异常
if (1 == 1) {
throw new RuntimeException("测试一下异常情况");
}
return "s1";
}).handle((s, t) -> {
if (t != null) {
return "hello world";
}
return s;
}).join();
System.out.println(result);
}
学习链接:
https://www.cnblogs.com/fingerboy/p/9948736.html
测试代码:
https://gitee.com/qiu_zheng/completable-future