JUC并发编程之:CompletableFuture (七)
一、概述
##一、CompletableFuture
1、创建异步操作:
CompletableFuture提供了四种方法来创建异步操作:
=============================================================================================
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
=============================================================================================
其中:没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行
runAsync方法不支持返回值,SupplyAsync支持返回值
【例子:juc5_use包下:CompletableFutureTest】
结论:future.get();会阻塞主线程向下接着执行,等异步执行完成后再向下执行,如果有返回值,其可以得到返回值
2、计算结果完成后的回调方法:
CompletableFuture完成异步执行后,可以执行集中特定的回调方法:
=============================================================================================
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)
=============================================================================================
从参数可以看到,这里可以处理 "正常的计算结果" 和 "异常情况"
其中:
whenComplete方法是执行当前任务的线程继续执行whenComplete方法,在异步正常/非正常执行完后,都会接着执行 whenComplete
whenCompleteAsync是把whenCompleteAsync这个任务提交给线程池来继续执行
exceptionally: 在异步执行发生异常时,会接着执行exceptionally,用以处理异常的情况
3、线程串行化执行
当一个线程依赖另一个线程时,可以使用 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)
=============================================================================================
从参数中可以看到:t为上一个任务返回的结果类型,u为当前任务要返回的结果类型
其中:
thenApply:串行化执行,thenApply方法执行需要依赖supplyAsync的结果时可以使用thenApply
当supplyAsync发生异常时,会直接执行exceptionally或直接抛出异常,不会继续执行thenApply
4、执行完任务对结果的处理
=============================================================================================
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);
=============================================================================================
handle 是执行任务完成时对结果的处理。
handle 方法和 thenApply 方法处理方式基本一样。
不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。
thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。
whenComplete接收的是BiConsumer,handler接收的是BiFunction;
BiConsumer是直接消费的,而BiFunction是有返回值的,
5、消费结果处理
接收任务的处理结果,并消费处理,无返回结果。
=============================================================================================
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 CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
=============================================================================================
thenAccept任务正常执行完后,消费上一步的处理结果,无返回值
thenRun任务正常执行完后,不关心且无法处理上一步的处理结果,只要上一步正常执行完后就开始执行thenRun方法,无返回值
6、合并任务:(有返回值)
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);
=============================================================================================
thenCombine处理两个completableStage的处理结果,并且返回(有返回值)
7、合并任务:(无返回值)
当两个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);
=============================================================================================
thenAcceptBoth处理两个completableStage的处理结果(无返回值)
8、两个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);
=============================================================================================
applyToEither:两个CompletionStage,谁返回快就用谁的结果进行下一步的操作(有返回值)
9、两个CompletableStage,谁返回快就用谁的结果进行下一步的操作(无返回值)(可以使用上面的结果)
=============================================================================================
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);
=============================================================================================
acceptEither:两个CompletableStage,谁返回快就用谁的结果进行下一步的操作(无返回值)
10、两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)(无返回值)(不可以使用上面的结果)
=============================================================================================
public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);
=============================================================================================
runAfterEither:两个CompletableStage,任何一个执行完了就可以执行runAferEither里的run方法,无法使用上面的处理结果,且无返回值
11、两个CompletionStage,都完成了计算才会执行下一步的操作(Runnable)(无返回值)(不可以使用上面的结果)
=============================================================================================
public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);
=============================================================================================
runAfterBoth:两个complatableStage,都执行完成了,才能执行runAfterBoth,无法使用上面的处理结果,且无返回值
12、thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。
=============================================================================================
public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) ;
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor) ;
=============================================================================================
二、示例
package com.lee.juc.juc5_use;
import com.lee.base.commons.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.util.concurrent.*;
import java.util.function.*;
/**
* 项目名称:basic
* 类 名 称:CompletableFutureTest
* 类 描 述:
* 创建时间:2021-08-26 11:49
* 创 建 人:Lee
*/
@Slf4j
public class CompletableFutureTest {
private ExecutorService executorService = Executors.newFixedThreadPool(5);
/**
* runAsync无返回值
* future.get()会阻塞主线程接着向下执行
*/
@Test
public void runAsyncTest() throws ExecutionException, InterruptedException {
log.info("test......start");
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("run async.......");
}, executorService);
future.get();
log.info("test......end");
}
/**
* applyAsync有返回值
* future.get()会阻塞祝线程接着向下执行,且可以获取返回值
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void applyAsyncTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
User u = new User(1, "lee", 20);
CompletableFuture<User> future = CompletableFuture.supplyAsync(() -> {
log.info("apply async.......");
return new User(1, "lee", 20);
}, executorService);
User user = future.get();
log.info("test------->result:{}", user);
log.info("test.......end");
}
/**
* whenComplete:在异步 正常/非正常执行完后,都会接着执行 whenComplete
* whenComplete:用以继续处理异步正常执行的结果,或异常情况
* (示例中:r为异步执行的结果,t为异常)
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void whenCompleteTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<User> future = CompletableFuture.supplyAsync(() -> {
log.info("supply async.......");
int a = 10 / 0;
return new User(1, "lee", 20);
}, executorService).whenComplete((r, t) -> {
log.info("whenComplete.......");
r.setAge(18);
return;
});
User user = future.get();
log.info("test------>result:{}", user);
log.info("test.......end");
}
/**
* exceptionally: 在异步执行发生异常时,会接着执行exceptionally
* exceptionally:用以继续处理异常的情况
* (示例中:t为异常)
*/
@Test
public void exceptionallyTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<User> future = CompletableFuture.supplyAsync(() -> {
log.info("supply async.......");
int i = 10 / 0;
return new User(1, "lee", 18);
}, executorService).exceptionally(t -> {
log.info("exceptionally.......e:{}", t);
return null;
});
User user = future.get();
log.info("test.......result:{}", user);
log.info("test.......end");
}
/**
* thenApply:串行化执行,thenApply方法执行需要依赖supplyAsync的结果时可以使用thenApply
* 当supplyAsync发生异常时,会直接执行exceptionally或直接抛出异常,不会继续执行thenApply
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void thenApplyTest() throws ExecutionException, InterruptedException {
log.info("test......start");
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
log.info("supply async.......");
int i = 10 / 0;
return 10;
}, executorService).thenApply(new Function<Integer, String>() {
@Override
public String apply(Integer params) {
log.info("then apply.......");
return params + " append 5";
}
}).exceptionally(t -> {
log.info("exception deal");
return null;
});
String res = future.get();
log.info("test.......result:{}", res);
log.info("test......end");
}
/**
* handle 是执行任务完成时对结果的处理。
* handle 方法和 thenApply 方法处理方式基本一样。
* <p>
* 不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。
* thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。
* <p>
* whenComplete接收的是BiConsumer,handler接收的是BiFunction;
* BiConsumer是直接消费的,而BiFunction是有返回值的,
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void handleTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
log.info("supply async.......");
int i = 10 / 0;
return 10;
}, executorService).handle(new BiFunction<Integer, Throwable, String>() {
@Override
public String apply(Integer params, Throwable throwable) {
return params + " append 5";
}
}).exceptionally(t -> {
log.info("exceptionally deal");
return null;
});
String res = future.get();
log.info("test.......res:{}", res);
log.info("test.......end");
}
/**
* 任务正常执行完后,消费上一步的处理结果,无返回值
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void thenAcceptTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
log.info("supply async.......");
//int i = 10 / 0;
return 10;
}, executorService).thenAccept(result -> {
log.info("then accept.......1 " + result);
if(result==10){
return;
}
log.info("then accept.......2 " + result);
}).exceptionally(t -> {
log.info("exceptionally.......");
return null;
});
future.get();
log.info("test.......end");
}
/**
* 任务正常执行完后,不关心且无法处理上一步的处理结果,
* 只要上一步正常执行完后就开始执行thenRun方法,无返回值
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void thenRunTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
log.info("supply async.......");
//int i = 10 / 0;
return 10;
}, executorService).thenRun(() -> {
log.info("then run.......");
}).exceptionally(t -> {
log.info("exceptionally.......");
return null;
});
future.get();
log.info("test.......end");
}
/**
* 处理两个completableStage的处理结果,并且返回(有返回值)
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void thenCombineTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 1 , supply async.......");
return "future1====>10 ";
}, executorService);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 2 , supply async.......");
int i = 10 / 0;
return "future2=====>20 ";
}, executorService).exceptionally(t -> {
log.info("future2 exceptionally");
return "exceptionally====>20";
});
CompletableFuture<Object> result = future1.thenCombine(future2, new BiFunction<String, String, Object>() {
@Override
public Object apply(String result1, String result2) {
log.info("");
return result1 + result2;
}
});
log.info("test.......time test");
String res = (String) result.get();
log.info("test.......result:{}", res);
log.info("test.......end");
}
/**
* 处理两个completableStage的处理结果(无返回值)
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void thenAcceptBothTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 1 , supply async.......");
return "future1====>10 ";
}, executorService);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 2 , supply async.......");
int i = 10 / 0;
return "future2=====>20 ";
}, executorService).exceptionally(t -> {
log.info("future2 exceptionally");
return "exceptionally====>20";
});
CompletableFuture<Void> results = future1.thenAcceptBoth(future2, new BiConsumer<String, String>() {
@Override
public void accept(String result1, String reuslt2) {
log.info(result1 + reuslt2);
}
});
results.get();
log.info("test.......end");
}
/**
* 两个CompletableStage,谁处理快就用谁的结果进行下一步操作,有返回值
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void applyToEitherTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 1 , supply async.......");
return "future1====>10 ";
}, executorService);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 2 , supply async.......");
int i = 10 / 0;
return "future2=====>20 ";
}, executorService).exceptionally(t -> {
log.info("future2 exceptionally");
return "exceptionally====>20";
});
CompletableFuture<Object> results = future1.applyToEither(future2, new Function<String, Object>() {
@Override
public Object apply(String firstResult) {
return "谁快就用谁的result:" + firstResult;
}
});
String res = (String) results.get();
log.info("test.......res:{}", res);
log.info("test.......end");
}
/**
* 两个CompletableStage,谁处理快就用谁的结果进行下一步处理,无返回值
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void acceptEitherTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 1 , supply async.......");
return "future1====>10 ";
}, executorService);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 2 , supply async.......");
int i = 10 / 0;
return "future2=====>20 ";
}, executorService).exceptionally(t -> {
log.info("future2 exceptionally");
return "exceptionally====>20";
});
CompletableFuture<Void> results = future1.acceptEither(future2, new Consumer<String>() {
@Override
public void accept(String firstResult) {
log.info("谁快就用谁的result:" + firstResult);
}
});
results.get();
log.info("test.......end");
}
/**
* 两个CompletableStage,任何一个执行完了就可以执行runAferEither里的run方法,
* 无法使用上面的处理结果,且无返回值
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void runAfterEitherTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 1 , supply async.......");
return "future1====>10 ";
}, executorService);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 2 , supply async.......");
int i = 10 / 0;
return "future2=====>20 ";
}, executorService).exceptionally(t -> {
log.info("future2 exceptionally");
return "exceptionally====>20";
});
CompletableFuture<Void> result = future1.runAfterEither(future2, new Runnable() {
@Override
public void run() {
log.info("上面任何一个future,执行完就可以执行这里的操作");
}
});
result.get();
log.info("test.......end");
}
/**
* 两个complatableStage,都执行完成了,才能执行runAfterBoth,无法使用上面的处理结果,且无返回值
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void runAfterBothTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 1 , supply async.......");
return "future1====>10 ";
}, executorService);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 2 , supply async.......");
int i = 10 / 0;
return "future2=====>20 ";
}, executorService).exceptionally(t -> {
log.info("future2 exceptionally");
return "exceptionally====>20";
});
CompletableFuture<Void> result = future1.runAfterBoth(future2, new Runnable() {
@Override
public void run() {
log.info("上面两个都处理完成了,才能执行这里");
}
});
result.get();
log.info("test.......end");
}
/**
* thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void thenComposeTest() throws ExecutionException, InterruptedException {
log.info("test.......start");
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("future 1 , supply async.......");
return "future1====>10 ";
}, executorService).thenCompose(new Function<String, CompletionStage<String>>() {
@Override
public CompletionStage<String> apply(String param) {
return CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "deal with res1:" + param + ", return res2";
}
});
}
});
String res = future1.get();
log.info("test.......result:{}", res);
log.info("test.......end");
}
}