异步调用实现一个不需要被等待的方法的返回值;让调用者(主线程)继续执行(异步执行);在 java 中,简单的讲就是开启另一个线程完成程序计算(子线程),使得调用者(主线程)继续执行,不需要等待计算的结果,但是调用者任然需要获取线程的计算结果(不需要同步阻塞等待)。调用后无需等待,任务交给子线程,主线程继续执行。
Future 也是一个异步计算结果返回接口,目的获取返回值结果。但是 future 在获取返回值结果的时候,方法必须同步阻塞等待返回值结果。
结论: futrure 对于结果获取不是很方便,只能通过同步阻塞的方式获取结果,或者是轮询的方式获取到结果;阻塞的方式获取返回值结果与异步的思想想违背,轮询方式又很占用 cpu 资源,也不能及时得到我们结果。
CompletableFuture 提供了 4 个静态的方法,来创建一个异步操作(异步开启: 从这 4 个静态的方法开发即可)
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)
代码示例:
@Slf4j
public class AsyncFutureDemo {
public static ThreadPoolExecutor executorPool = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
9, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*异步编排无返回值*/
/*RunAsync : 不传线程池,则默认使用的线程池 ForkJoinPool.commonPool*/
/*RunAsync : 这里使用自定义的线程池*/
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// 业务代码执行
int j = 100 / 3;
log.info("子线程{},线程执行结果{}",Thread.currentThread().getName(),j);
},executorPool);
/*调用异步任务*/
future.get();
log.info("主线程end");
}
}
CompletableFuture 可以帮助我们简化异步编程复杂性,提供了函数式编程的能力,可以通 过回调函数的方式处理计算结果。
public class CompletableFuture<T> implements Future<T>, CompletionStage<T>
CompletableFuture 具有Future的特性,还实现了CompletionStage接口,具备CompletionStage 接口的特性: 串行执行,并行执行,聚合(AND 聚合,OR 聚合)
串行关系执行: then – 然后,也就是表示下一步,所以通常是一个串行的关系体现,then 后面的单词(比如 run/apply/accept)就是函数是接口中抽象方法名称; 串行关系执行: 利用上一步的执行结果,去进行下一步任务执行,任务执行具有先后顺序, 因此把这种操作叫做串行关系。Async 表示异步。
查看Function 接收参数查看参数的情况 void accept(T t, U u);
public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor
executor);
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 <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor);
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*supplyAsync有返回值*/
/* thenRun 没有返回值,只和上一步有顺序关系,不关心上一步执行结果。 */
/*最终无返回值*/
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
// 业务代码执行
int j = 100 / 3;
log.info("子线程{},线程执行结果{}",Thread.currentThread().getName(),j);
return j;
}).thenRun(()->{
log.info("thenRun{}运行...",Thread.currentThread().getName());
});
/*调用异步任务*/
future.get();
log.info("主线程end");
}
thenCompose 的使用示例
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Long> thenCompose = CompletableFuture.supplyAsync(() -> {
int j = 100 / 3;
log.info("子线程{},线程执行结果{}", Thread.currentThread().getName(), j);
return j;
}).thenCompose(new Function<Integer, CompletionStage<Long>>() {
@Override
public CompletionStage<Long> apply(Integer u) {
// 第二次执行
CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
log.info("子线程开始,参数{}",u);
Long res = Long.valueOf(u * 5);
return res;
});
return future;
}
});
Long aLong = thenCompose.get();
log.info("主线程end,结果{}",aLong);
}
thenCombine、thenAcceptBoth、runAfterBoth 都是要求两者都执行完毕,也就是 and 且的关系。
// thenCombine: 把2 个阶段的 CompletionStage 都执行完毕后,把结果一块交给 thenAcceptBoth 进行执行,有返回值
public <U,V> CompletionStage<V> thenCombine (CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);
// thenAcceptBoth: 当2个阶段的 CompletionStage 都执行完毕后,把结果一块交给 thenAcceptBoth 进行执行,没有返回值
public <U> CompletionStage<Void> thenAcceptBoth (CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
// runAfterBoth: 当2个阶段的 CompletionStage 都执行完毕后,才会执行下一个操作
public CompletionStage<Void> runAfterBoth(CompletionStage<?> other, Runnable action);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
int j = 100 / 3;
log.info("子线程{},线程执行结果{}", Thread.currentThread().getName(), j);
return j;
});
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
int j = 100 / 4;
log.info("子线程{},线程执行结果{}", Thread.currentThread().getName(), j);
return j;
});
CompletableFuture<Long> thenCombine = f1.thenCombine(f2, (u, t) -> {
/*u t 分别是两个阶段的结果*/
Long res = Long.valueOf(u + t);
return res;
});
Long aLong = thenCombine.get();
log.info("主线程end,结果{}", aLong);
}
关键词Either
// 两个阶段,将计算结果最快的结果作为下一步处理的消费,有返回值
public <U> CompletionStage<U> applyToEitherAsync (CompletionStage<? extends T> other, Function<? super T, U> fn);
// 两个阶段,将计算结果最快的结果作为下一步处理的消费,无返回值
public CompletionStage<Void> acceptEither (CompletionStage<? extends T> other, Consumer<? super T> action);
//两个阶段,其中一个执行完后,执行无参数传递,无返回值
public CompletionStage<Void> runAfterEitherAsync (CompletionStage<?> other, Runnable action);
@Slf4j
public class AsyncFutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
int j = 100 / 3;
log.info("子线程{},线程执行结果{}", Thread.currentThread().getName(), j);
return j;
});
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
int j = 100 / 4;
log.info("子线程{},线程执行结果{}", Thread.currentThread().getName(), j);
return j;
});
CompletableFuture<Long> thenCombine = f1.applyToEither(f2, (t) -> {
/*u t 分别是两个阶段的结果*/
Long res = (long) t;
return res;
});
Long aLong = thenCombine.get();
log.info("主线程end,结果{}", aLong);
}
public CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn);
public CompletionStage<T> whenComplete (BiConsumer<? super T, ? super Throwable> action);
public <U> CompletionStage<U> handle (BiFunction<? super T, Throwable, ? extends U> fn);
@Slf4j
public class AsyncFutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
int j = 100 / 4;
log.info("子线程{},线程执行结果{}", Thread.currentThread().getName(), j);
return j;
}).exceptionally(throwable -> {
log.error("执行错误{}", throwable.getMessage());
return null;
}
);
Integer aLong = f1.get();
log.info("主线程end,结果{}", aLong);
}