多线程之异步编排CompletableFuture

多线程的实现方式有哪些
三种实现方案:
    1>继承Thread类的方法实现多线程
    2>实现Runnable接口的方式实现多线程
    3>利用Callable和Funture接口的方式实现多线程

1.2不能得到返回值,3可以获取返回值

三种方式都不可以控制资源

在项目代码中以上三种方式都不可取,需要使用线程池(将所有的多线程异步任务都交给线程池执行)确保系统的稳定运行

开发中为什么使用线程池

认识CompletableFuture

1.创建异步对象


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);

1.run开头的方法都是没有返回值的,supply的方法都是可以获取返回结果的

2.使用CompletableFuture异步编排大多方法都会有一个重载方法,会多出一个executor参数,用来传来自定义的线程池,如果不传就会使用默认的线程池。

CompletableFuture可用于线程异步编排,使原本串行执行的代码,变为并行执行,提高代码执行速度

简单使用:

CompletableFuture.whenComplete():用于接收带有返回值的CompletableFuture对象,无法修改返回值。

CompletableFuture.exceptionally():用于处理异常,只要异步线程中有抛出异常,则进入该方法,修改返回值。

CompletableFuture.handle():用于处理返回结果,可以接收返回值和异常,可以对返回值进行修改。

无返回值

有返回值 方法计算成功时回调 出现异常抓获并且给出默认值

 有返回值 方法无论执行成功失败都回调 对结果做判断处理

线程串行化

// 使线程串行执行,不接受A方法的返回值,无返回值
public CompletableFuture<Void> thenRun(Runnable action);
public CompletableFuture<Void> thenRunAsync(Runnable action);
public CompletableFuture<Void> thenRunAsync(Runnable action, Executor executor);

// 使线程串行执行,接受A方法的返回值,无返回值
public CompletableFuture<Void> thenAccept(Consumer<? super T> action);
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor);

// 使线程串行执行,接受A方法的返回值,有返回值
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);

thenApply方法,当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值

thenAccept方法,消费处理结果.接受前置任务的处理结果,并消费处理,无返回结果

thenRun方法,只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行thenRun的后续操作

带有Asyc默认都是异步执行的

以上都需要前置任务成功完成

 thenRunAsync

 

 thenAcceptAsync

 thenApplyAsync

两任务组合  全部执行完再执行新任务

两任务并行执行,并且都执行完成之后,串行另一个任务,也就是说在两个任务执行并行执行完成之后,需要再执行另一个任务

// 线程并行执行完成,并且执行新任务action,新任务无入参,无返回值
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other, Runnable action);
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action);
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action, Executor executor);

// 线程并行执行完成,并且执行新任务action,新任务有入参,无返回值
public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action, Executor executor);

// 线程并行执行完成,并且执行新任务action,新任务有入参,有返回值
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);

thenCombine:组合两个future,获取两个future的返回结果,并返回给当前任务的返回值thenAcceptBoth,组合两个future,获取两个future任务的返回结果,然后处理任务.没有返回值

runAfterBoth:组合两个future,不需要获取future的结果,只需要两个future处理完任务后,处理该任务

如果这里让线程2休眠 线程2无法执行完 就会导致任务3无法执行 即不满足任务12都执行完毕所以任务3不会执行

两任务并行执行,其中一个执行完,就执行新任务。

两任务并行执行,只要其中有一个执行完,就开始执行新任务。

// 任务并行执行,只要其中有一个执行完,就开始执行新任务action,新任务无入参,无返回值
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other, Runnable action);
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action);
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action, Executor executor);

// 任务并行执行,只要其中有一个执行完,就开始执行新任务action,新任务有入参(入参类型为Object,因为不确定是哪个任务先执行完成),无返回值
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action);
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action);
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor);

// 任务并行执行,只要其中有一个执行完,就开始执行新任务action,新任务有入参(入参类型为Object,因为不确定是哪个任务先执行完成),有返回值
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn);
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn);
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn,Executor executor);

 

 多任务组合(所有任务都执行完毕后返回)

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs);

allOf方法 等待所有任务完成

anyOf方法 只要有一个任务完成

CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> "加载资源1", executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> "加载资源2", executor);
CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "加载资源3";
}, executor);

// 串联起若干个线程任务, 没有返回值
CompletableFuture<Void> all = CompletableFuture.allOf(future01, future02, future03);
// 等待所有线程执行完成
// .join()和.get()都会阻塞并获取线程的执行情况
// .join()会抛出未经检查的异常,不会强制开发者处理异常 .get()会抛出检查异常,需要开发者处理
all.join();
all.get();

如果不将异步任务放入线程池,当其中一个业务阻塞的时候方法线程运行结束,但是异步任务还没执行完毕,会导致无返回值响应

放入线程池后方法会阻塞,这样所有的异步任务都会执行完毕

结合项目优化主页渲染数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值