Java8 CompletableFuture 异步执行

2022-08-03 11:29:42

1.简介

CompletableFuture 是 JDK8 提供的一个异步执行工具。

示例1:

publicstaticvoidmain(String[] args)throws ExecutionException, InterruptedException{
    CompletableFuture<Void> future= CompletableFuture.runAsync(()->{for(int i=0; i<3; i++){
            System.out.println(i);try{
                Thread.sleep(1000L);}catch(InterruptedException ignored){}}
        System.out.println("Future Finished.");});
    System.out.println("Main Thread Finished.");
    future.get();}

输出结果1:

2.异步执行

CompletableFuture 提供了两个方法用于异步执行:

  • CompletableFuture.runAsync没有返回值
  • CompletableFuture.supplyAsync有返回值

示例:

publicstaticvoidmain(String[] args)throws ExecutionException, InterruptedException{// runAsync 没有返回值
    CompletableFuture<Void> future1= CompletableFuture.runAsync(()-> System.out.println("future1 executed."));// supplyAsync 有返回值
    CompletableFuture<Object> future2= CompletableFuture.supplyAsync(()->{
        System.out.println("future2 executed.");return"result";});

    System.out.println("future1.get(): "+ future1.get());
    System.out.println("future2.get(): "+ future2.get());}

输出结果:

3.守护线程

CompletableFuture返回的Future默认为守护线程,如果不调用get()获取结果,主线程结束后会自动结束。主要有以下4种情景:

  • 情景1: 执行时间 > 主线程时间,异步线程会执行
  • 情景2: 执行时间 > 主线程,是守护线程,会被杀死,异步线程不会执行
  • 情景3: 执行时间 > 主线程,但是不是守护线程,不会被杀死,异步线程会执行
  • 情景4: ExecutorService.submit(),默认不是守护线程,不会被杀死,异步线程会执行

示例:

publicstaticvoidmain(String[] args){
    ExecutorService executorService= Executors.newFixedThreadPool(2);// 1.执行时间 < 主线程,会打印
    CompletableFuture<Void> future1= CompletableFuture.runAsync(()->
		System.out.println("Thread1 是否为守护线程 : "+ Thread.currentThread().isDaemon()));// 2.执行时间 > 主线程,是守护线程,会被杀死,不会打印
    CompletableFuture.runAsync(()->{try{
            Thread.sleep(3000L);
            System.out.println("Thread2 是否为守护线程 : "+ Thread.currentThread().isDaemon());}catch(InterruptedException e){
            e.printStackTrace();}});// 3.执行时间 > 主线程,但是不是守护线程,不会被杀死,会打印
    CompletableFuture.runAsync(()->{try{
            Thread.sleep(1000L);
            System.out.println("Thread3 等待1秒");
            System.out.println("Thread3 是否为守护线程 : "+ Thread.currentThread().isDaemon());}catch(InterruptedException e){
            e.printStackTrace();}}, executorService);// 4.ExecutorService.submit(),默认不是守护线程,不会被杀死,会打印。
    executorService.submit(()->{try{
            Thread.sleep(2000L);
            System.out.println("Thread4 等待2秒");
            System.out.println("Thread4 是否为守护线程 : "+ Thread.currentThread().isDaemon());}catch(InterruptedException e){
            e.printStackTrace();}});// 主线程执行完毕
    System.out.println("Main Thread Finished.");
    executorService.shutdown();}

输出结果2:

4.处理执行结果

CompletableFuture还封装了很多处理执行结果操作。操作太多,列举比较常用的几种:

  • thenAccept(): 对结果进行使用;
  • thenApply(): 对结果进行转换;
  • exceptionally(): 对异常进行处理;
  • whenComplete(): 相当于 thenAccept() + thenApply() + exceptionally().

示例:

publicstaticvoidmain(String[] args){// thenAccept对结果进行使用
    System.out.println("------------------------------");
    CompletableFuture.supplyAsync(()->"Thread1 Finished.").thenAccept(System.out::println);// thenApply对结果进行转换
    System.out.println("------------------------------");
    CompletableFuture.supplyAsync(()->"Thread2 Finished.").thenApply(s-> s+" + thenApply()").thenAccept(System.out::println);// exceptionally对异常进行处理
    System.out.println("------------------------------");
    CompletableFuture.supplyAsync(()->{thrownewRuntimeException("Thread3 Failed.");}).exceptionally(Throwable::toString).thenAccept(System.out::println);// 主线程执行完毕
    System.out.println("------------------------------");
    System.out.println("Main Thread Finished.");}

输出结果:

whenComplete() 示例:

publicstaticvoidmain(String[] args)throws ExecutionException, InterruptedException{// thenAccept对结果进行使用
    System.out.println("------------------------------");
    CompletableFuture<String> future= CompletableFuture.supplyAsync(()->"Thread1 Finished.").whenComplete(newBiConsumer<String, Throwable>(){@Overridepublicvoidaccept(String s, Throwable throwable){
            System.out.println("result: "+ s);
            System.out.println("throwable: "+ throwable);}});// exceptionally对异常进行处理
    System.out.println("------------------------------");
    CompletableFuture.supplyAsync(()->{thrownewRuntimeException("Thread3 Failed.");}).whenComplete(newBiConsumer<Object, Throwable>(){@Overridepublicvoidaccept(Object s, Throwable throwable){
            System.out.println("result: "+ s);
            System.out.println("throwable: "+ throwable);}});

    System.out.println("------------------------------");
    System.out.println("future.get(): "+ future.get());// 主线程执行完毕
    System.out.println("------------------------------");
    System.out.println("Main Thread Finished.");}

输出结果:

整理完毕,完结撒花~

  • 作者:ACGkaka_
  • 原文链接:https://blog.csdn.net/qq_33204709/article/details/118107794
    更新时间:2022-08-03 11:29:42