CompletableFuture基本用法及总结

一,CompletableFuture 异步编排

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

//传入一个Runnable,特点是无需返回值
public static CompletableFuture<Void> runAsync(Runnable runnable)
//传入一个Runnable,特点是无需返回值,可以指定在那个线程池中执行,即Executor
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
//传入一个要执行的异步任务,但是有返回值
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
//传入一个要执行的异步任务,但是有返回值,可以指定在那个线程池中执行,即Executor
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)

1,创建异步方法

(1),使用runAsync测试

public class CompletableFutureTest {
    //创建线程池,不建议使用该方法创建,本文主要是讲解CompletableFuture,线程池部分不详细介绍
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) {
        System.out.println("main方法开始。。。");
        CompletableFuture.runAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
        },executor);//使用我们自己的线程池
        System.out.println("main方法结束。。。");
    }
}

运行结果:
main方法开始。。。
main方法结束。。。
当前线程:11
运行结果:5
(2),使用supplyAsync测试

public class CompletableFutureTest {
    //创建线程池,不建议使用该方法创建,本文主要是讲解CompletableFuture,线程池部分不详细介绍
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main方法开始。。。");
        //只要启动异步任务,都会返回一个CompletableFuture
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor);
        //获取异步任务的返回值
        Integer integer = future.get();
        System.out.println("main方法结束。。。" + integer);
    }
}

运行结果
main方法开始。。。
当前线程:11
运行结果:5
main方法结束。。。5
(3),总结
1,runXxxx 都是没有返回结果的,supplyXxx 都是可以获取返回结果的
2,可以传入自定义的线程池,否则就用默认的线程池;

2,CompletableFuture完成回调与异常感知

计算完成时回调方法

public completableFuture<T> whenComplete(BiConsumer <? super T,? super Throwable> action);
public completableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable>action);
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable>action,Executor executor);
public completableFuture<T> exceptiona1ly(Function<Throwable,? extends T fn);

细节
1,whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。
2,whenComplete 和 whenCompleteAsync 的区别:
(1), whenComplete:是执行当前任务的线程执行继续执行whenComplete 的任务。
(2),whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池 来进行执行。

public class CompletableFutureTest {
    //创建线程池,不建议使用该方法创建,本文主要是讲解CompletableFuture,线程池部分不详细介绍
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main方法开始。。。");
        //只要启动异步任务,都会返回一个CompletableFuture
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果:" + i);
            return i;
        }, executor).whenComplete((res,exception) -> {
            //虽然能得到异常信息,但是没法修改返回数据
            System.out.println("异步任务成功完成了。。。结果是:" + res + "异常是:" + exception);
        }).exceptionally(throwable -> {
            //可以感知异常,同时返回默认值
            return 10;
        });
        //获取异步任务的返回值
        Integer integer = future.get();
        System.out.println("main方法结束。。。" + integer);
    }
}

运行结果
main方法开始。。。
当前线程:11
异步任务成功完成了。。。结果是:null异常是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
main方法结束。。。10
注意
有异常才会进入exceptionally()方法,没有异常正常返回,

3,handle方法 (最终处理)

public class CompletableFutureTest {
    //创建线程池,不建议使用该方法创建,本文主要是讲解CompletableFuture,线程池部分不详细介绍
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main方法开始。。。");
        
        //方法执行完成后的处理
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor).handle((res,exec) -> {
            if (res != null){
                return res * 2;
            }
            if (exec != null){
                return 0;
            }
            return 0;
        });
        //获取异步任务的返回值
        Integer integer = future.get();
        System.out.println("main方法结束。。。" + integer);
    }
}

运行结果
main方法开始。。。
当前线程:11
运行结果:5
main方法结束。。。20

注意:和 complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。

4,线程串行化方法

public <Us CompletableFuture<Us thenApply(Function<? super T,? extends Us fn)
public <UsCompletableFuturecUz thenApplyAsyne(Function<? super T,? extends us fn)
public <U> completableFuture<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,Executorexecutor);

public completionstage<Void> thenRun(Runnable action) ;
public completionstage<void> thenRunAsync(Runnable action);
public completionStage<Void> thenRunAsync(Runnable action,Executor executor );

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

		//thenApplyAsync:能接受上一步的结果,有返回值
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            return "Hello" + res;
        }, executor);
        String s = future.get();
        //获取异步任务的返回值
        System.out.println("main方法结束。。。" + s);

(2), thenAccept 方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。

		//thenAcceptAsync:能接受上一步结果,但是无返回值
		CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor).thenAcceptAsync(res -> {
            System.out.println("任务2启动了。。。" + res);
        },executor);
        //获取异步任务的返回值
        System.out.println("main方法结束。。。" );

(3),thenRun 方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行 thenRun 的后续操作 带有 Async 默认是异步执行的。同之前。 以上都要前置任务成功完成。

 		//thenRun:不能获取到上一步的执行结果,无返回值
        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, executor).thenRunAsync(() -> {
            System.out.println("任务2启动了。。。");
        },executor);
        //获取异步任务的返回值
        System.out.println("main方法结束。。。" );

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

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<? superT,? 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);

public UCompletableFuture<Void> thenAcceptBoth(Completionstage<? extends U> other ,Biconsumer<? super T, ? super U>action);
public <Us Completab1eFuture<void>thenAcceptBothAsync(CompletionStage<? extends U> other ,BiConsumer<? super T?super U>action);
public <UsCompletab1eFuture<Void> thenAcceptBothAsync(completionstage<? extends U> other ,Biconsumer<? super T, ? super U>action,Executor executor);
	
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);

(1),thenCombine:组合两个 future,获取两个 future 的返回结果,并返回当前任务的返回值

		CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            System.out.println("任务2结束:");
            return "hello";
        }, executor);
        CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return f1 + ":::" + f2 + "->>world";
        }, executor);

        //获取异步任务的返回值
        System.out.println("main方法结束。。。" + future.get());
        /**
         * 运行结果
         * main方法开始。。。
         * 任务1线程:11
         * 任务1结束:
         * 任务2线程:12
         * 任务2结束:
         * main方法结束。。。5:::hello->>world
         */

(2),thenAcceptBoth:组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有 返回值。

		CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            System.out.println("任务2结束:");
            return "hello";
        }, executor);
        future01.thenAcceptBothAsync(future02,(f1,f2) -> {
            System.out.println("任务3开始----》之前的结果:" + f1 + "===>" + f2);
        },executor);

        //获取异步任务的返回值
        System.out.println("main方法结束。。。");
        /**
         * 运行结果
         * main方法开始。。。
         * 任务1线程:11
         * 任务1结束:
         * 任务2线程:12
         * 任务2结束:
         * main方法结束。。。
         * 任务3开始----》之前的结果:5===>hello
         */

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

CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            System.out.println("任务2结束:");
            return "hello";
        }, executor);
        future01.runAfterBothAsync(future02,() -> {
            System.out.println("任务3开始");
        },executor);
        //获取异步任务的返回值
        System.out.println("main方法结束。。。");
		/**
         * 运行结果
         * main方法开始。。。
         * 任务1线程:11
         * 任务1结束:
         * main方法结束。。。
         * 任务2线程:12
         * 任务2结束:
         * 任务3开始
         */

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

public <U>completab1eFuture<U applyToEither(completionstage<? extends T> other,Function<? super T, U> fn);
public <U> completableFuturecU> applyToEither Async(completionstage<? extends T> other ,Function<? super TU> fn);
public <UCompletableFuture<Ux applyToEither Asyne(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 comp1etab1eFuture<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 runAfterEither Async(Completionstage<?> other ,Runnable action,Executor executor);

当两个任务中,任意一个 future 任务完成的时候,执行任务。
(1),applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。

		//applyToEitherAsync感知结果,有返回值
		CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束:");
            return i;
        }, executor);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("任务2结束:");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }, executor);
        CompletableFuture<String> future = future01.applyToEitherAsync(future02, res -> {
            System.out.println("任务3开始。。。之前的结果:" + res);
            return res.toString() + "===>很爱很爱你";
        }, executor);
        //获取异步任务的返回值
        System.out.println("main方法结束。。。" + future.get() );
        /**
         * 运行结果
         * main方法开始。。。
         * 任务1线程:11
         * 任务1结束:
         * 任务3开始。。。之前的结果:5
         * main方法结束。。。5===>很爱很爱你
         * 任务2线程:12
         */

(2),acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。

		//acceptEitherAsync:感知结果,无返回值
		CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束:");
            return i;
        }, executor);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("任务2结束:");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }, executor);
        future01.acceptEitherAsync(future02,res -> {
            System.out.println("任务3开始。。。之前的结果:" + res);
        },executor);
        //获取异步任务的返回值
        System.out.println("main方法结束。。。" );
        /**
         * 运行结果
         * main方法开始。。。
         * main方法结束。。。
         * 任务2线程:12
         * 任务1线程:11
         * 任务1结束:
         * 任务3开始。。。之前的结果:5
         */

(3),runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返 回值。

		//两个任务,只要有一个完成,我们就执行任务3
		//runAfterEitherAsync:不感知结果,也无返回值
		CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("任务2结束:");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }, executor);
        future01.runAfterEitherAsync(future02,() -> {
            System.out.println("任务3开始。。。之前的结果");
        },executor);
        //获取异步任务的返回值
        System.out.println("main方法结束。。。" );
        /**
         * 运行结果
         * main方法开始。。。
         * 任务1线程:11
         * 任务1结束:
         * 任务2线程:12
         * main方法结束。。。
         * 任务3开始。。。之前的结果
         * 任务2结束:
         */

7,多任务组合

public static completableFuture<Void>a110f(completableFuture<?>...cfs);
public static completableFuture<object> anyof(CompletableFuture<?>... cfs);

(1),allOf:等待所有任务完成 anyOf:只要有一个任务完成

		CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("上厕所");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "蹲马桶";
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("刷抖音");
            return "看小姐姐跳舞";
        }, executor);

        CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {
            System.out.println("抽烟");
            return "吸芙蓉王";
        }, executor);

        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
        allOf.get();//等待所有结果完成


        //获取异步任务的返回值
        System.out.println("main方法结束。。。" + future01.get() + future02.get() + future03.get());
        /**
         * 运行结果
         * main方法开始。。。
         * 刷抖音
         * 抽烟
         * 上厕所
         * main方法结束。。。蹲马桶看小姐姐跳舞吸芙蓉王
         */

(2),anyOf:只要有一个任务完成

		CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("上厕所");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "蹲马桶";
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("刷抖音");
            return "看小姐姐跳舞";
        }, executor);

        CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {
            System.out.println("抽烟");
            return "吸芙蓉王";
        }, executor);

        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future01, future02, future03);

        //获取异步任务的返回值
        System.out.println("main方法结束。。。" + anyOf.get());
        /**
         * 运行结果
         * main方法开始。。。
         * 刷抖音
         * main方法结束。。。看小姐姐跳舞
         * 抽烟
         */
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值