理解同步与异步区别

同步:就是在发出一个功能调用时,在没有得到结果之前,将一直处于等待中 即阻塞状态。也就是必须一件一件事做,等前一件做完了才能做下一件事

异步:异步通常意味着非阻塞,可以使得我们的任务单独运行在与主线程分离的其他线程中,并且通过回调可以在主线程中得到异步任务的执行状态,是否完成,和是否异常等信息。

CompletableFuture 简介

CompletableFuture 在 Java 里面被用于异步编程,异步通常意味着非阻塞, 可以使得我们的任务单独运行在与主线程分离的其他线程中,并且通过回调可以在主线程中得到异步任务的执行状态,是否完成,和是否异常等信息。
CompletableFuture 实现了 Future, CompletionStage 接口,实现了 Future接口就可以兼容现在有线程池框架,而 CompletionStage 接口才是异步编程 的接口抽象,里面定义多种异步方法,通过这两者集合,从而打造出了强大的 CompletableFuture 类。

Future 与 CompletableFuture

Futrue 在 Java 里面,通常用来表示一个异步任务的引用,比如我们将任务提 交到线程池里面,然后我们会得到一个 Futrue,在 Future 里面有 isDone 方 法来 判断任务是否处理结束,还有 get 方法可以一直阻塞直到任务结束然后获取结果,但整体来说这种方式,还是同步的,因为需要客户端不断阻塞等待或者不断轮询才能知道任务是否完成。

Future 的主要缺点如下:

1)不支持手动完成
我提交了一个任务,但是执行太慢了,我通过其他路径已经获取到了任务结果, 现在没法把这个任务结果通知到正在执行的线程,所以必须主动取消或者一直 等待它执行完成
2)不支持进一步的非阻塞调用
通过 Future 的 get 方法会一直阻塞到任务完成,但是想在获取任务之后执行
额外的任务,因为 Future 不支持回调函数,所以无法实现这个功能
3)不支持链式调用
对于 Future 的执行结果,我们想继续传到下一个 Future 处理使用,从而形成
一个链式的 pipline 调用,这在 Future 中是没法实现的。
4)不支持多个 Future合并
比如我们有 10 个 Future 并行执行,我们想在所有的 Future 运行完毕之后, 执行某些函数,是没法通过 Future 实现的。
5)不支持异常处理
Future 的 API 没有任何的异常处理的 api,所以在异步运行时,如果出了问题 是不好定位的。

CompletableFuture 有 2个 异步方法 

异步调用没有返回值方法runAsync

异步调用有返回值方法supplyAsync
 注意  测试时 创建 CompletableFuture 时建议 添加线程池参数  ,如果不添加 默认使用的是 ForkJoinPool.commonPool 的线程池  但是 如果main主线程 结束 整个 任务也将会结束

使用 CompletableFuture

场景:主线程里面创建一个 CompletableFuture,然后主线程调用 get 方法会阻塞,最后我们在一个子线程中使其终止
/*** 主线程里面创建一个 CompletableFuture,然后主线程调用 get 方法会阻塞,最后我们在一个子线程中使其终止* @param args*/public static void main(String[] args) throws Exception{CompletableFuture<String> future = new CompletableFuture<>();new Thread(() -> {try{System.out.println(Thread.currentThread().getName() + "子线程开始干活");//子线程睡 5 秒Thread.sleep(5000);//在子线程中完成主线程future.complete("success");}catch (Exception e){e.printStackTrace();}}, "A").start();//主线程调用 get 方法阻塞System.out.println("主线程调用 get 方法获取结果为: " + future.get());System.out.println("主线程完成,阻塞结束!!!!!!");}
没有返回值的异步任务

   public static void main(String[] args) throws Exception {System.out.println("主线程开始");//运行一个没有返回值的异步任务CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {try {System.out.println("子线程启动干活");Thread.sleep(5000);System.out.println("子线程完成");} catch (Exception e) {e.printStackTrace();}});//主线程阻塞future.get();System.out.println("主线程结束");}
有返回值的异步任务
    /*** 有返回值的异步任务* @param args*/public static void main(String[] args) throws Exception{System.out.println("主线程开始");//运行一个有返回值的异步任务CompletableFuture<String> future =CompletableFuture.supplyAsync(() -> {try {System.out.println("子线程开始任务");Thread.sleep(5000);} catch (Exception e) {e.printStackTrace();}return "子线程完成了!";});//主线程阻塞String s = future.get();System.out.println("主线程结束, 子线程的结果为:" + s);}

线程依赖

当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。
 private static Integer num = 10;/*** 先对一个数加 10,然后取平方** @param args*/public static void main(String[] args) throws Exception {System.out.println("主线程开始");CompletableFuture<Integer> future =CompletableFuture.supplyAsync(() -> {try {System.out.println("加 10 任务开始");num += 10;} catch (Exception e) {e.printStackTrace();}return num;}).thenApply(integer -> {return num * num;});Integer integer = future.get();System.out.println("主线程结束, 子线程的结果为:" + integer);
消费处理结果

thenAccept 消费处理结果, 接收任务的处理结果,并消费处理,无返回结果。  

private static Integer num = 10;public static void main(String[] args) throws Exception {System.out.println("主线程开始");CompletableFuture.supplyAsync(() -> {try {System.out.println("加 10 任务开始");num += 10;} catch (Exception e) {e.printStackTrace();}return num;}).thenApply(integer -> {return num * num;}).thenAccept(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println("子线程全部处理完成,最后调用了 accept,结果为:" +integer);}});}
异常处理

exceptionally 异常处理,出现异常时触发 

    private static Integer num = 10;public static void main(String[] args) throws Exception {System.out.println("主线程开始");CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {int i = 1 / 0;System.out.println("加 10 任务开始");num += 10;return num;}).exceptionally(ex -> {//异常内容输出System.out.println(ex.getMessage());return -1;});System.out.println(future.get());}
handle 类似于 thenAccept/thenRun 方法,是最后一步的处理调用,但是同时可以处理异常
private static Integer num = 10;public static void main(String[] args) throws Exception {System.out.println("主线程开始");CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {//  int i= 1/0;System.out.println("加 10 任务开始");num += 10;return num;}).handle((i, ex) -> {System.out.println("进入 handle 方法");if (ex != null) {System.out.println("发生了异常,内容为:" + ex.getMessage());return -1;} else {System.out.println("正常完成,内容为: " + i);return i;}});System.out.println(future.get());}
结果合并
thenCompose 合并两个有依赖关系的 CompletableFutures 的执行结果
private static Integer num = 10;public static void main(String[] args) throws Exception {System.out.println("主线程开始");//第一步加 10CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {System.out.println("加 10 任务开始");num += 10;return num;});//合并CompletableFuture<Integer> future1 = future.thenCompose(i ->//再来一个 CompletableFutureCompletableFuture.supplyAsync(() -> {return i + 1;}));System.out.println(future.get());System.out.println(future1.get());}

thenCombine 合并两个没有依赖关系的 CompletableFutures 任务

    private static Integer num = 10;public static void main(String[] args) throws Exception {System.out.println("主线程开始");CompletableFuture<Integer> job1 = CompletableFuture.supplyAsync(() -> {System.out.println("加 10 任务开始");num += 10;return num;});CompletableFuture<Integer> job2 = CompletableFuture.supplyAsync(() -> {System.out.println("乘以 10 任务开始");num = num * 10;return num;});//合并两个结果CompletableFuture<Object> future = job1.thenCombine(job2, newBiFunction<Integer, Integer, List<Integer>>() {@Overridepublic List<Integer> apply(Integer a, Integer b) {List<Integer> list = new ArrayList<>();list.add(a);list.add(b);return list;}});System.out.println("合并结果为:" + future.get());}
合并多个任务的结果 allOf 与 anyOf
allOf: 一系列独立的 future 任务,等其所有的任务执行完后做一些事情    
allOf返回的CompletableFuture是多个任务都执行完成后才会执行,只有有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。
    private static Integer num = 10;/*** 先对一个数加 10,然后取平方* @param args*/public static void main(String[] args) throws Exception{System.out.println("主线程开始");List<CompletableFuture> list = new ArrayList<>();CompletableFuture<Integer> job1 = CompletableFuture.supplyAsync(() -> {System.out.println("加 10 任务开始");num += 10;return num;});list.add(job1);CompletableFuture<Integer> job2 = CompletableFuture.supplyAsync(() -> {System.out.println("乘以 10 任务开始");num = num * 10;return num;});list.add(job2);CompletableFuture<Integer> job3 = CompletableFuture.supplyAsync(() -> {System.out.println("减以 10 任务开始");num = num - 10;return num;});list.add(job3);CompletableFuture<Integer> job4 = CompletableFuture.supplyAsync(() -> {System.out.println("除以 10 任务开始");num = num / 10;return num;});list.add(job4);//多任务合并List<Integer> collect =list.stream().map(CompletableFuture<Integer>::join).collect(Collectors.toList());System.out.println(collect);}
    private static Integer num = 10;/*** 先对一个数加 10,然后取平方* @param args*/public static void main(String[] args) throws Exception{System.out.println("主线程开始");List<CompletableFuture> list = new ArrayList<>();CompletableFuture<Integer> job1 = CompletableFuture.supplyAsync(() -> {System.out.println("加 10 任务开始");num += 10;return num;});list.add(job1);CompletableFuture<Integer> job2 = CompletableFuture.supplyAsync(() -> {System.out.println("乘以 10 任务开始");num = num * 10;return num;});list.add(job2);CompletableFuture<Integer> job3 = CompletableFuture.supplyAsync(() -> {System.out.println("减以 10 任务开始");num = num - 10;return num;});list.add(job3);CompletableFuture<Integer> job4 = CompletableFuture.supplyAsync(() -> {System.out.println("除以 10 任务开始");num = num / 10;return num;});list.add(job4);CompletableFuture<Void> future = CompletableFuture.allOf(job1, job2, job3, job4).whenComplete((a, b) -> {// b为异常对象if (b != null) {System.out.println("error stack trace->");b.printStackTrace();} else {System.out.println("run succ,result->" + a);}});System.out.println(future.get());}
anyOf: 只要在多个 future 里面有一个返回,整个任务就可以结束,而不需要等到每一个
future 结束
    private static Integer num = 10;/*** 先对一个数加 10,然后取平方** @param args*/public static void main(String[] args) throws Exception {System.out.println("主线程开始");CompletableFuture<Integer>[] futures = new CompletableFuture[4];CompletableFuture<Integer> job1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(5000);System.out.println("加 10 任务开始");num += 10;return num;} catch (Exception e) {return 0;}});futures[0] = job1;CompletableFuture<Integer> job2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);System.out.println("乘以 10 任务开始");num = num * 10;return num;} catch (Exception e) {return 1;}});futures[1] = job2;CompletableFuture<Integer> job3 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(3000);System.out.println("减以 10 任务开始");num = num  - 10;return num;} catch (Exception e) {return 2;}});futures[2] = job3;CompletableFuture<Integer> job4 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(4000);System.out.println("除以 10 任务开始");num = num / 10;return num;} catch (Exception e) {return 3;}});futures[3] = job4;CompletableFuture future = CompletableFuture.anyOf(futures);System.out.println(future.get());}

①. 获得结果和触发计算(get、getNow、join、complete)

getNow ()方法  如果计算完成 返回计算完成后的结果  如果调用时没有完成 则返回一个指定的替代值

重点  join  与get 区别 

join方法和get( )方法作用一样,不同的是,join方法不抛出异常

这些不予操作演示

②. 对计算结果进行处理(thenApply、handle) 将线程串行化

①. public <U> CompletableFuture<U> thenApply

计算结果存在依赖关系,这两个线程串行化
由于存在依赖关系(当前步错,不走下一步),当前步骤有异常的话就叫停

②. public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn):
有异常也可以往下一步走,根据带的异常参数可以进一步处理

③. whenComplete:是执行当前任务的线程执行继续执行whenComplete的任务

④. whenCompleteAsync:是执行把whenCompleteAsync这个任务继续提交给线程池来进行执行

        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {try { TimeUnit.SECONDS.sleep(1);  } catch (InterruptedException e) {e.printStackTrace();}return 1;}).thenApply(s->{// 这个s 是指上一步的返回值System.out.println("-----1");//如果加上int error=1/0; 由于存在依赖关系(当前步错,不走下一步),当前步骤有异常的话就叫        停//int error=1/0;return s+1;}).thenApply(s->{System.out.println("-----2");return s+2;}).whenComplete((v,e)->{// v 是指 异步操作数据的返回值  e指上面操作是否出现异常if(e==null){System.out.println("result-----"+v);}}).exceptionally(e->{e.printStackTrace();return null;});System.out.println(Thread.currentThread().getName()+"\t"+"over....");try { TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {e.printStackTrace();}

handle()与thenApply 效果相同 但是  thenApply 出现异常,线程立即停止  而handle 不会出现线程停止问题 会继续执行代码,同时也可以处理异常  等同于 thenApply() 和 exceptionally()结合

// 创建异步执行任务:CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(()->{return 1;}).thenApply((i)->{int q  = 1/0;System.out.println("我被处以0了");return  i+2;}).handle((i,e)->{if (e == null){return i +3;}else {e.printStackTrace();System.out.println("处理0");return 9;}});try { TimeUnit.SECONDS.sleep(2);  } catch (InterruptedException e) {e.printStackTrace();}System.out.println(cf.get());

③. 对计算结果进行消费(thenRun、thenAccept、thenApply)

①. thenRun(Runnable runnable)
任务A执行完执行B,并且B不需要A的结果 相当于另起一个线程

②. CompletableFuture<Void> thenAccept(Consumer<? super T> action)
任务A执行完成执行B,B需要A的结果,但是任务B    无返回值

③. public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
任务A执行完成执行B,B需要A的结果,同时任务B    有返回值

这些不予操作演示

某些方法 后缀 有Async 和没有 Async 后缀的方法的区别

带了Async的方法表示的是:会重新在线程池中启动一个线程来执行任务  这个线程池指的是CompletableFuture 创建时的默认线程池 即 ForkJoinPool.commonPool

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)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)public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor)

④. 对计算速度进行选用(applyToEither、acceptEither、runAfterEither)

①. public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)
这个方法表示的是,谁快就用谁的结果

applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值
acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值
runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返回值

applyToEither使用

    CompletableFuture<String> playA = CompletableFuture.supplyAsync(() -> {System.out.println("A come in");try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }return "playA";});CompletableFuture<String> playB = CompletableFuture.supplyAsync(() -> {System.out.println("B come in");try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }return "playB";});CompletableFuture<String> result = playA.applyToEither(playB, f -> {return f + " is winer";});System.out.println(Thread.currentThread().getName()+"\t"+"-----: "+result.join());

---------------------------------------------------------------------------------------------------------------------------

System.out.println(CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {e.printStackTrace();}return 1;}).applyToEither(CompletableFuture.supplyAsync(() -> {try { TimeUnit.SECONDS.sleep(2);  } catch (InterruptedException e) {e.printStackTrace();}return 2;}), r -> {return r;}).join());

runAfterEither 使用

      CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}return 1;});CompletableFuture<Integer> integerCompletableFuture2 = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return 2;});CompletableFuture<Void> voidCompletableFuture = integerCompletableFuture.runAfterEither(integerCompletableFuture2, () -> System.out.println(integerCompletableFuture2.join()));System.out.println(voidCompletableFuture.join());

带了Async的方法表示的是:会重新在线程池中启动一个线程来执行任务  这个线程池指的是CompletableFuture 创建时的默认线程池 即 ForkJoinPool.commonPool

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

⑤. 对计算结果进行合并(thenCombine、thenAcceptBoth、runAfterBoth)

①. public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)
两个CompletionStage任务都完成后,最终把两个任务的结果一起交给thenCombine来处理
先完成的先等着,等待其他分支任务

 thenCombine 使用

有返回值

CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}return 1;});CompletableFuture<Integer> integerCompletableFuture2 = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return 2;});CompletableFuture<Integer> future = integerCompletableFuture.thenCombine(integerCompletableFuture2, (a, b) -> a + b);System.out.println(future.join());

------------------------------------------------  简化-------------------------------------

  CompletableFuture<Integer>  future = CompletableFuture.supplyAsync(() ->2).thenCombine(CompletableFuture.supplyAsync(() ->1),(a, b) ->a+b);System.out.println(future.join());

thenAcceptBoth 使用 无返回值

CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}return 1;});CompletableFuture<Integer> integerCompletableFuture2 = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return 2;});CompletableFuture<Void> voidCompletableFuture1 = integerCompletableFuture.thenAcceptBoth(integerCompletableFuture2, (a, b) -> System.out.println(a + b));

------------------------------------------------------ 简化-----------------------------------------------------

   CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> 1).thenAcceptBoth(CompletableFuture.supplyAsync(() -> 2), (a, b) -> System.out.println(a + b));System.out.println(voidCompletableFuture.join());

runAfterBoth 使用 无返回值

    CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}return 1;});CompletableFuture<Integer> integerCompletableFuture2 = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return 2;});CompletableFuture<Void> voidCompletableFuture1 = integerCompletableFuture.runAfterBoth(integerCompletableFuture2, () -> System.out.println(integerCompletableFuture.join()+integerCompletableFuture2.join()));

----------------------------------------- 简化 ---------------------------------------------

CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> 1).runAfterBoth(CompletableFuture.supplyAsync(() -> 2),()-> System.out.println()) ;

thenCompose   合并两个有依赖关系的 CompletableFutures 的执行结果

thenCompose方法会在某个任务执行完成后,将该任务的执行结果作为方法入参然后执行指定的方法,该方法会返回一个新的CompletableFuture实例,如果该CompletableFuture实例的result不为null,则返回一个基于该result的新的CompletableFuture实例;如果该CompletableFuture实例为null,则,然后执行这个新任务,测试用例如下:

CompletableFuture<Integer> integerCompletableFuture2 = CompletableFuture.supplyAsync(() -> {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return 2;});CompletableFuture<Integer> future= integerCompletableFuture2.thenCompose(param->{System.out.println(param);return CompletableFuture.supplyAsync(()-> param+ 2);});System.out.println( future.join());

---------  简化 -----------------------------------

  CompletableFuture.supplyAsync(() ->2).thenCompose(param ->{return CompletableFuture.supplyAsync(()-> param+ 2);});

⑥. 多任务组合(allOf、anyOf)

①. allOf:等待所有任务完成
(public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs))

②. anyOf:只要有一个任务完成
(public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs))

 CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {System.out.println("查询商品的图片信息");return "hello.jpg";});CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {System.out.println("查询商品的属性");return "黑色+256G";});CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {try { TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {e.printStackTrace();}System.out.println("查询商品介绍");return "华为";});//需要全部完成
//        futureImg.get();
//        futureAttr.get();
//        futureDesc.get();//CompletableFuture<Void> all = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);//all.get();CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);anyOf.get();System.out.println(anyOf.get());System.out.println("main over.....");

同步与异步参考博客

同步与异步的区别(一看则懂)_小柠檬爱编程的博客-CSDN博客_同步异步的区别

Java面试题之:同步与异步?进程与线程?并发与并行?_faramita_of_mine的博客-CSDN博客_同步异步面试题

Java之阻塞和非阻塞以及同步和异步的区别_笑看风云路的博客-CSDN博客_java 异步阻塞

java 同步和异步_Java中的同步与异步详细介绍_时光派的博客-CSDN博客

Java --- 线程同步和异步的区别_怪伽先森的博客-CSDN博客_java线程同步和异步的区别

CompletableFuture 用法参考博客

JUC高并发编程从入门到精通(全)_码农研究僧的博客-CSDN博客_juc并发编程

Juc09_CompletableFuture概述、创建方式、常用API、电商比价需求_所得皆惊喜的博客-CSDN博客_completablefuture.allof

Java8 CompletableFuture 用法全解_孙大圣666的博客-CSDN博客_completablefuture

CompletableFuture详解~allOf_gqltt的博客-CSDN博客_completablefuture.allof

Java8 CompletableFuture(7) CompletableFuture allOf 获取所有线程结果_亚 瑟的博客-CSDN博客_completablefuture.allof

java 异步编程 CompletableFuture相关推荐

  1. 阿里技术专家加多:Java异步编程实战之基于JDK中的Future实现异步编程 | 文末赠书...

    正文共:14244 字 8 图 预计阅读时间: 36 分钟 本节内容摘自<Java异步编程实战>中的一小节. 一.前言 本节主要讲解如何使用JDK中的Future实现异步编程,这包含如何使 ...

  2. Java 异步编程:从 Future 到 Loom

    众所周知,Java 开始方法执行到结束,都是由同一个线程完成的.这种方式虽易于开发调试,但容易因为锁.IO 等原因导致线程挂起,产生线程上下文切换.随着对应用并发能力要求越来越高,频繁的线程上下文切换 ...

  3. 认识Java异步编程

    一 .认识异步编程 通常Java开发人员喜欢使用同步代码编写程序,因为这种请求(request)/响应(response)的方式比较简单,并且比较符合编程人员的思维习惯;这种做法很好,直到系统出现性能 ...

  4. 阿里技术专家加多:Java异步编程实战之基于JDK中的Future实现异步编程

    正文共:14244 字 8 图 预计阅读时间: 36 分钟 本节内容摘自<Java异步编程实战>中的一小节. 一.前言 本节主要讲解如何使用JDK中的Future实现异步编程,这包含如何使 ...

  5. java 异步_浅谈Java异步编程

    本文来自网易云社区. Java异步编程引言 Java的异步编程其实是一个充分利用计算机CPU资源,不想让主程序阻塞在某个长时间运行的任务上,这类耗时的任务可以是IO操作.远程调用以及高密度计算任务.如 ...

  6. 《Java8实战》读书笔记10:组合式异步编程 CompletableFuture

    <Java8实战>读书笔记10:组合式异步编程 CompletableFuture 第11章 CompletableFuture:组合式异步编程 11.1 Future 接口 (只是个引子 ...

  7. Java 异步编程 (5 种异步实现方式详解)

    同步操作如果遇到一个耗时的方法,需要阻塞等待,那么我们有没有办法解决呢?让它异步执行,下面我会详解异步及实现 @mikechen 目录 什么是异步? 一.线程异步 二.Future异步 三.Compl ...

  8. 淘宝资深java技术专家整理分享java异步编程实战文档

    前言 本文由淘宝资深java技术专家爆肝整理分享的java异步编程实战文档,针对常见异步编程场景,从编程语言.开发框架等角度深入讲解异步编程的原理和方法,每个技术点都附有案例代码! 通常Java开发人 ...

  9. 超赞!阿里资深P9架构师总结出第一本《Java异步编程实战》

    什么是异步编程: 传统的同步编程是一种请求响应模型,调用一个方法,等待其响应返回 异步编程就是要重新考虑是否需要响应的问题,也就是缩小需要响应的地方.因为越快获得响应,就是越同步化,顺序化,事务化,性 ...

  10. Java中如何使用非阻塞异步编程——CompletableFuture

    分享一波:程序员赚外快-必看的巅峰干货 对于Node开发者来说,非阻塞异步编程是他们引以为傲的地方.而在JDK8中,也引入了非阻塞异步编程的概念.所谓非阻塞异步编程,就是一种不需要等待返回结果的多线程 ...

最新文章

  1. crontab安装_django-crontab实现服务端的定时计划任务
  2. desktop docker 无法卸载_Docker容器无法停止或移除-权限被拒绝错误
  3. 提到刺这种兵器的guandan
  4. 在打字稿中,是什么! (惊叹号/ bang)运算符取消引用成员时?
  5. 容器技术Docker K8s 7 容器服务ACK集群
  6. html可视区高度,你真的懂js获取可视区宽高吗
  7. 证券交易1-交易系统简介
  8. 创业者必备知识SWOT分析模型+案例分析
  9. 解决fences2.01在win8.1的状态下无法移动桌面图标问题
  10. 如何在Web页面里使用高拍仪扫描上传图像
  11. 启动优化之一——启动分析及优化方案
  12. myChat - 第三方ChatGPT原生客户端,支持win和mac系统
  13. 8-2 sdust-Java-文件读取与统计【人工判编程题】 (30 分)
  14. 基于深度学习的三维重建算法综述
  15. Flutter——Flutter初探与Dart基础
  16. Linux平台上DPDK入门指南(二)
  17. 服务器维修故障诊断思路大全
  18. sqlserver 查询记录数 查系统表秒出
  19. 2022年全球市场数字电位器IC总体规模、主要生产商、主要地区、产品和应用细分研究报告
  20. 数独(日语:数独/すうどく sūdoku)

热门文章

  1. 有监督学习和无监督学习
  2. sublime-text-3-build-3207 破解+注册码
  3. oracle 经纬度格式转换,GOOGLE与百度经纬度互转(plsql版)
  4. 统计学之偏度系数和峰度系数
  5. 如何成为一名数据分析师 | 推荐收藏
  6. 51job简历如何导出pdf格式
  7. pandas处理df函数及plt绘图函数(作业总结笔记待补充...)
  8. 001-前端课程介绍
  9. python转换js_将节点js转换为python-seri
  10. 如何将区块链技术用于版权保护?