JAVA8 CompletableFuture 异步编排 异步回调 案例实现 源码解析

JUC CompletableFuture 异步编排

使用场景:

​ 当业务逻辑复杂时,特别是在微服务下,有些数据还需要远程调用.多个业务逻辑独立运行将耗费更多的时间.

例如:

  • 查询商品基本信息 -> 0.5s
  • 查询商品库存信息(远程调用) -> 1s
  • 查询商品图片 -> 0.5s
  • 查询商品规格属性 (依赖商品基本信息查询结果) -> 0.5s
  • 提交所有商品信息 (依赖其他查询结果) -> 1s

所有应用使用单线程顺序执行时将需要2.5s才能完成.如果有多个线程同时操作(需要注意数据的依赖性),也许只需要2.5s.

使用CompletableFuture 异步编排实现场景:

  • 分析各个异步任务之间的数据依赖
  • 分析各个异步任务是否有返回值
public class CompletableFutureDemo {
    
    
    //自定义线程池
    private static ExecutorService service = new ThreadPoolExecutor(5,
                                                                    10,
                                                                    30,
                                                                    TimeUnit.SECONDS,
                                                                    new LinkedBlockingDeque<Runnable>(3),
                                                                    Executors.defaultThreadFactory(),
                                                                    new ThreadPoolExecutor.AbortPolicy());
    public  static void main(String args[]){
    
    
        //三个没有数据依赖的可并行线程
        CompletableFuture<String> futureBasic = CompletableFuture.supplyAsync(() -> {
    
    
            System.out.println("商品基本信息对象查询完成");
            return "商品基本信息对象";
        }, service);
        CompletableFuture<String> futureWare = CompletableFuture.supplyAsync(() -> {
    
    
            //TODO 远程调用库存服务模块
            System.out.println("商品库存对象查询完成");
            return "商品库存对象";
        }, service);
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
    
    
            System.out.println("商品图片对象查询完成");
            return "商品图片对象";
        }, service);

        //线程串行化方法 查询商品规格属性   (依赖商品基本信息查询结果)
        CompletableFuture<String> futureInfo = futureBasic.thenApplyAsync((basicResult) -> {
    
    
            //从basicResult 中获取商品基本信息  查询商品规格属性
            System.out.println("商品规格属性对象查询完成");
            return "商品规格属性对象";
        }, service);

        //当4个商品对象的信息查询线程全部结束后,开启提交所有商品信息线程
        CompletableFuture<Void> futureFinish = CompletableFuture.allOf(futureBasic, futureWare, futureImg, futureInfo);


        try {
    
    
            //等待所有线程结束
            futureFinish.get();
            CompletableFuture<Void> futureCommit = CompletableFuture.runAsync(() -> {
    
    
                System.out.println("商品提交");
            }, service);

            //调用对应CompletableFuture.get方法获取返回值
            System.out.println(futureBasic.get());
            System.out.println(futureWare.get());
            System.out.println(futureImg.get());
            System.out.println(futureInfo.get());

        }catch(Exception e) {
    
    
            e.printStackTrace();
        }

    }
}

运行结果:

商品基本信息对象查询完成
商品库存对象查询完成
商品图片对象查询完成
商品规格属性对象查询完成
商品基本信息对象
商品库存对象
商品图片对象
商品规格属性对象
商品提交

1. 创建异步对象

CompletableFuture提供了四个静态方法来创建一个异步操作

  • runAsync 传入Runnable接口参数,不产生返回值
  • supplyAsync 传入Supplier供给型接口参数,产生一个返回值
  • 两个方法均可以传入自定义的线程池对象 Executor
    java8 四大函数式接口

源码解析:

Executor参数接受一个线程池对象:

public interface ExecutorService extends Executor {
    
    

Supplier是一个供给型函数式接口:

@FunctionalInterface
public interface Supplier<T> {
    
    
    /**
     * Gets a result.
     * @return a result
     */
    T get();
}

runAsync 不产生返回值

public static CompletableFuture<Void> runAsync(Runnable runnable) {
    
    
    return asyncRunStage(asyncPool, runnable);
}
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor) {
    
    
    return asyncRunStage(screenExecutor(executor), runnable);
}

supplyAsync 产生一个返回值

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
    
    
    return asyncSupplyStage(asyncPool, supplier);
}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor) {
    
    
    return asyncSupplyStage(screenExecutor(executor), supplier);
}

测试:

1. runAsync(Runnable,Executor):

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
        //runAsync
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    
    
            System.out.println(Thread.currentThread().getName());
            int i = 5;
            System.out.println(i);
        }, executor);
        System.out.println("main end ....");
    }

}

输出:

main start ....
main end ....
pool-1-thread-1
5

2. supplyAsync(Supplier supplier,Executor executor):

package com.rwp.gulimail.search.thread;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
        CompletableFuture<Student> future = CompletableFuture.supplyAsync(() ->{
    
    
            return new Student("彷徨的我第一次尝试",22);
        }, executor);
        try {
    
    
            //阻塞等待,获取结果
            Student student = future.get();
            System.out.println(student);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }

        System.out.println("main end ....");
    }
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    public static class Student{
    
    
        private String name;
        private Integer age;

    }
}

输出:

main start ....
CompletableFutureDemo.Student(name=彷徨的我第一次尝试, age=22)
main end ....

2. 计算完成时回调方法

**作用:**当上一步创建的异步对象成功后可用设置回调方法.

CompletableFuture提供了四个方法来进行计算完成时的回调;用于异步对象完成后执行

  • whenComplete 用于异步对象完成后执行, 传入一个具有2个参数的函数型接口BiConsumer<T, U> ,其中T为任意对象,U为异常对象.
  • whenCompleteAsync,与whenComplete 功能相同.区别:当异步回调任务完成后以异步的方式将任务转交线程池,由其他线程继续执行后续回调方法.
  • whenCompleteAsync方法均可以传入自定义的线程池对象 Executor
  • exceptionally方法用来处理异常情况,传入一个函数式接口Function<T, R>,apply传入参数T,返回结果R
  • exceptionally和whenComplete 的区别:
    • whenComplete 虽然能得到异常信息,但是没法修改返回数据
    • exceptionally 可用感知异常,同时返回默认值

源码解析:

Function<T, R>:

@FunctionalInterface
public interface Function<T, R> {
    
    

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);

BiConsumer<T, U>

@FunctionalInterface
public interface BiConsumer<T, U> {
    
    
    /**
     * Performs this operation on the given arguments.
     *
     * @param t the first input argument
     * @param u the second input argument
     */
    void accept(T t, U u);
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {
    
    
    return uniWhenCompleteStage(null, action);
}
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action) {
    
    
    return uniWhenCompleteStage(asyncPool, action);
}
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor) {
    
    
    return uniWhenCompleteStage(screenExecutor(executor), action);
}
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn) {
    
    
        return uniExceptionallyStage(fn);
    }

测试:

1.whenComplete:

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");


        CompletableFuture<Student> future = CompletableFuture.supplyAsync(() ->{
    
    
//            int error =10 /0;
            return new Student("彷徨的我第一次尝试",22);
        }, executor).whenComplete((result,exception)->{
    
    
            if(exception == null){
    
    
                System.out.println("异步回调成功完成,结果是:"+result+"如果错误:");
            }else {
    
    
                System.out.println("异常是:"+exception);
            }
        });

        System.out.println("main end ....");
    }
}

正常运行结果:

main start ....
main end ....
异步回调成功完成,结果是:CompletableFutureDemo.Student(name=彷徨的我第一次尝试, age=22)

异常运行结果:

main start ....
异常是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
main end ....

2.exceptionally

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");


        CompletableFuture<Student> future = CompletableFuture.supplyAsync(() ->{
    
    
            int error =10 /0;
            return new Student("彷徨的我第一次尝试",22);
        }, executor).whenComplete((result,exception)->{
    
    
            //虽然能得到异常信息,但是没法修改返回数据
            if(exception == null){
    
    
                System.out.println("异步回调成功完成,结果是:"+result);
            }
        }).exceptionally(throwable->{
    
    
            //感知异常,修改返回数据
            //返回结果设置为默认返回
            return new Student("默认返回",200);
        });

        try {
    
    
            System.out.println(future.get());
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }

        System.out.println("main end ....");
    }
}

结果:

main start ....
CompletableFutureDemo.Student(name=默认返回, age=200)
main end ....

3. handle方法

**作用:Complete方法一样,可用对结果做最后的处理(可处理异常),可改变返回值.

类似于**Complete+exceptionally

CompletableFuture提供了三个handle方法:

  • 分为异步和同步方法,区别与**Complete方法相同;
  • 可以传入一个双参数的函数式接口BiFunction<T, U, R>,apply方法接受T,U两个参数,返回R类型对象
  • handleAsync方法均可以传入自定义的线程池对象 Executor

源码解析:

@FunctionalInterface
public interface BiFunction<T, U, R> {
    
    

    /**
     * Applies this function to the given arguments.
     *
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);
public <U> CompletableFuture<U> handle(
    BiFunction<? super T, Throwable, ? extends U> fn) {
    
    
    return uniHandleStage(null, fn);
}

public <U> CompletableFuture<U> handleAsync(
    BiFunction<? super T, Throwable, ? extends U> fn) {
    
    
    return uniHandleStage(asyncPool, fn);
}

public <U> CompletableFuture<U> handleAsync(
    BiFunction<? super T, Throwable, ? extends U> fn, Executor executor) {
    
    
    return uniHandleStage(screenExecutor(executor), fn);
}

测试:

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");

        CompletableFuture<Student> future = CompletableFuture.supplyAsync(() ->{
    
    
//            int error =10 /0;
            return new Student("彷徨的我第一次尝试",22);
        }, executor).handle((result,exception) ->{
    
    
            //产生异常
            if(exception != null ){
    
    
                return new Student("默认返回",200);
            }
            result.setName("handle二次处理的名字");
            return result;
        });

        try {
    
    
            System.out.println(future.get());
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("main end ....");
    }
}

正常结果:

main start ....
CompletableFutureDemo.Student(name=handle二次处理的名字, age=22)
main end ....

异常结果:

main start ....
CompletableFutureDemo.Student(name=默认返回, age=200)
main end ....

4. 线程串行化方法

**作用:**将两个线程任务串联执行(例如有数据依赖的任务之间)

CompletableFuture提供的3组9个方法实现线程串行化**

  • thenRun*: 指明下一步运行的任务,可以传入一个Runnable接口和Executor线程池(异步情况下Async),不接受上一步线程的返回结果.不产生返回值
  • thenAccept*: 指明下一步运行的任务,可以传入一个Consumer消费型接口(接受一个参数T,没有返回值)和Executor线程池(异步情况下Async),接受上一步线程的返回结果T.不产生返回值
  • thenApply*: 指明下一步运行的任务,可以传入一个Function函数型接口(接受一个参数T,返回一个R)和Executor线程池(异步情况下Async),接受上一步线程的返回结果T.产生返回值R

源码解析:

public CompletableFuture<Void> thenRun(Runnable action) {
    
    
    return uniRunStage(null, action);
}
public CompletableFuture<Void> thenRunAsync(Runnable action) {
    
    
    return uniRunStage(asyncPool, action);
}
public CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor) {
    
    
    return uniRunStage(screenExecutor(executor), action);
}
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
    
    
    return uniAcceptStage(null, action);
}
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
    
    
    return uniAcceptStage(asyncPool, action);
}
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor) {
    
    
    return uniAcceptStage(screenExecutor(executor), action);
}
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn) {
    
    
    return uniApplyStage(null, fn);
}
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn) {
    
    
    return uniApplyStage(asyncPool, fn);
}
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) {
    
    
    return uniApplyStage(screenExecutor(executor), fn);
}

测试:

1.thenRunAsync

public class CompletableFutureDemo {
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
        System.out.println("main start ....");
        
        CompletableFuture<Student> future1 = CompletableFuture.supplyAsync(() ->{
            return new Student("彷徨的我第一次尝试",22);
        }, executor);
        future1.thenRunAsync(()->{
            System.out.println("thenRunAsync 无法获取上一步运行结果");
        },executor);

        System.out.println("main end ....");
    }
}

结果:

main start ....
main end ....
thenRunAsync 无法获取上一步运行结果

2.thenAcceptAsync

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");


        CompletableFuture<Student> future1 = CompletableFuture.supplyAsync(() ->{
    
    
            return new Student("彷徨的我第一次尝试",22);
        }, executor);
        future1.thenAcceptAsync((result)->{
    
    
            System.out.println("thenAcceptAsync 可以获取上一步运行结果" +result);
        },executor);

        System.out.println("main end ....");
    }
}

结果:

main start ....
main end ....
thenAcceptAsync 可以获取上一步运行结果CompletableFutureDemo.Student(name=彷徨的我第一次尝试, age=22)

3.supplyAsync

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");


        CompletableFuture<Student> future1 = CompletableFuture.supplyAsync(() ->{
    
    
            return new Student("彷徨的我第一次尝试",22);
        }, executor);
        CompletableFuture<Student> future2 = future1.thenApplyAsync(result -> {
    
    
            System.out.println("thenApplyAsync 可以获取上一步运行结果" + result);
            result.setName("被thenApplyAsync修改后的名字");
            return result;
        }, executor);
        try {
    
    
            System.out.println(future2.get());
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }

        System.out.println("main end ....");
    }
}

结果:

main start ....
thenApplyAsync 可以获取上一步运行结果CompletableFutureDemo.Student(name=彷徨的我第一次尝试, age=22)
CompletableFutureDemo.Student(name=被thenApplyAsync修改后的名字, age=22)
main end ....

5. 两任务组合 -都要完成

**作用:**当两个异步任务必须都完成时,触发该任务.

CompletableFuture提供的3组9个方法实现两

  • runAfterBoth*: 指明一个运行的异步任务和传入一个Runnable接口和Executor线程池(异步情况下Async),当当前任务和第一个参数异步任务都完成后,执行Runable接口,不接受上一步线程的返回结果.不产生返回值
  • thenAcceptBoth*: 指明一个运行的异步任务和传入一个Consumer消费型接口(接受两个参数T,U为前2个异步任务的返回结果,没有返回值)和Executor线程池(异步情况下Async),当当前任务和第一个参数异步任务都完成后,执行Runable接口,接受上一步线程的返回结果T,U.不产生返回值
  • thenApply*: 指明一个运行的异步任务和传入一个Function函数型接口(接受两个参数T,U为前2个异步任务的返回结果,返回一个R)和Executor线程池(异步情况下Async),当当前任务和第一个参数异步任务都完成后,执行Runable接口,接受上一步线程的返回结果T,U.产生返回值R

源码解析:

public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);
public <U> CompletionStage<Void> thenAcceptBothAsync
    (CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,Executor executor);
public <U,V> CompletionStage<V> thenCombineAsync
    (CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);

测试:

thenCombineAsync:

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");


        CompletableFuture<Student> future1 = CompletableFuture.supplyAsync(() ->{
    
    
            return new Student("彷徨的我第一次尝试",22);
        }, executor);

        CompletableFuture<Student> future2 = CompletableFuture.supplyAsync(() ->{
    
    
            return new Student("彷徨的我第二次尝试",23);
        }, executor);
        CompletableFuture<Student> future3 = future1.thenCombineAsync(future2, (t, u) -> {
    
    
            System.out.println(t + "   " + u);
            return new Student("彷徨的我第三次尝试", 24);
        }, executor);
        try {
    
    
            System.out.println(future3.get());
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("main end ....");
    }
}

**结果:**当future1和future2都执行完成后,future3才执行

main start ....
CompletableFutureDemo.Student(name=彷徨的我第一次尝试, age=22)   CompletableFutureDemo.Student(name=彷徨的我第二次尝试, age=23)
CompletableFutureDemo.Student(name=彷徨的我第三次尝试, age=24)
main end ....

6. 两任务组合 - 一个完成

**作用:**只要其中一个异步任务完成时,触发该任务.

使用方法与两任务同时完成触发相同

源码:

public <U> CompletableFuture<U> applyToEitherAsync(
    CompletionStage<? extends T> other, Function<? super T, U> fn,
    Executor executor) {
    
    
    return orApplyStage(screenExecutor(executor), other, fn);
}
public CompletableFuture<Void> acceptEitherAsync(
    CompletionStage<? extends T> other, Consumer<? super T> action,
    Executor executor) {
    
    
    return orAcceptStage(screenExecutor(executor), other, action);
}
public CompletableFuture<Void> acceptEitherAsync(
    CompletionStage<? extends T> other, Consumer<? super T> action,
    Executor executor) {
    
    
    return orAcceptStage(screenExecutor(executor), other, action);
}

测试:

applyToEitherAsync:

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");

        CompletableFuture<Student> future1 = CompletableFuture.supplyAsync(() ->{
    
    
            return new Student("彷徨的我第一次尝试",22);
        }, executor);

        CompletableFuture<Student> future2 = CompletableFuture.supplyAsync(() ->{
    
    
            return new Student("彷徨的我第二次尝试",23);
        }, executor);
        CompletableFuture<Student> future3 = future1.applyToEitherAsync(future2, (t) -> {
    
    
            System.out.println(t + "   ");
            return new Student("彷徨的我第三次尝试", 24);
        }, executor);

        try {
    
    
            System.out.println(future3.get());
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("main end ....");
    }
}

结果:

main start ....
CompletableFutureDemo.Student(name=彷徨的我第一次尝试, age=22)   
CompletableFutureDemo.Student(name=彷徨的我第三次尝试, age=24)
main end ....

7. 多任务组合

**作用:**多任务进行组合,当一个(anyof)或多个(allof)任务完成时,触发该任务.

CompletableFuture提供两个静态方法实现多任务组合:

  • anyof和allof 均可以传递多个CompletableFuture 对象作为参数
  • anyof 没有返回值;allof有返回值

源码:

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
    
    
    return andTree(cfs, 0, cfs.length - 1);
}
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
    
    
    return orTree(cfs, 0, cfs.length - 1);
}

测试:

1.allOf

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]) throws ExecutionException, InterruptedException {
    
    
        System.out.println("main start ....");

        CompletableFuture<Student> future1 = CompletableFuture.supplyAsync(() ->{
    
    
            Student s = new Student("彷徨的我第一次尝试", 22);
            System.out.println(s);
            return s;
        }, executor);

        CompletableFuture<Student> future2 = CompletableFuture.supplyAsync(() ->{
    
    
            Student s = new Student("彷徨的我第二次尝试", 23);
            System.out.println(s);
            return s;
        }, executor);
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(future1, future2);
        voidCompletableFuture.get();//等待所有结果完成

        System.out.println("main end ....");
    }
}

结果:

main start ....
CompletableFutureDemo.Student(name=彷徨的我第一次尝试, age=22)
CompletableFutureDemo.Student(name=彷徨的我第二次尝试, age=23)
main end ....

2.anyof

public class CompletableFutureDemo {
    
    
    //创建一个基础线大小为10的程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    public  static void main(String args[]) throws ExecutionException, InterruptedException {
    
    
        System.out.println("main start ....");

        CompletableFuture<Student> future1 = CompletableFuture.supplyAsync(() ->{
    
    
            Student s = new Student("彷徨的我第一次尝试", 22);
            System.out.println(s);
            return s;
        }, executor);

        CompletableFuture<Student> future2 = CompletableFuture.supplyAsync(() ->{
    
    
            Student s = new Student("彷徨的我第二次尝试", 23);
            System.out.println(s);
            return s;
        }, executor);
        CompletableFuture<Object> voidCompletableFuture = CompletableFuture.anyOf(future1, future2);
        System.out.println(voidCompletableFuture.get()); //等待一个成功

        System.out.println("main end ....");
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44634197/article/details/108345777