CompletableFuture 异步编排

194 阅读4分钟

CompletableFuture

使用场景:

查询: 一个方法要返回A数据,但是A数据由B,C,D组成。其中C,D 查询需要依赖B数据的结果查询,为加快查询速度C,D并发执行, 这个时候可以用CompletableFuture解决。

    public static void Test5() {
        //线程池
        ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(5, 16, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        ArrayList<String> A = new ArrayList<>();
        // 创建异步执行任务:
        CompletableFuture<String> B = CompletableFuture.supplyAsync(() -> {
            A.add("B");
            //B返回
            return "B";
        }, THREAD_POOL_EXECUTOR);
        //thenApplyAsync:有返回值
        //thenAcceptAsync:无返回值
        CompletableFuture<String> C = B.thenApplyAsync((result) -> {
            //这里需要B的结果做些操作
            String c = result + "C";
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            A.add(c);
            return c;
        }, THREAD_POOL_EXECUTOR);

        CompletableFuture<String> D = B.thenApplyAsync((result) -> {
            //这里需要B的结果做些操作
            String d = result + "D";
            A.add(d);
            return d;
        }, THREAD_POOL_EXECUTOR);

        try {
            CompletableFuture.allOf(D, C).get();
            System.out.println(A);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//运行结果
//[B, BD, BC]


简单使用:

import java.util.ArrayList;
import java.util.concurrent.*;

public class Test {

    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(5, 16, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws Exception {
        //    Test.Test1();
        Test.Test5();
    }

    /**
     * 常用:
     * supplyAsync 创建带返回值的异步任务的
     * runAsync 创建无返回值的异步任务的
     */
    public static void Test1() {
        CompletableFuture<String> infoFuture1 = CompletableFuture.supplyAsync(() -> {
            //1、sku基本信息的获取  pms_sku_info
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "infoFuture1";
        }, THREAD_POOL_EXECUTOR);
        try {
            // 等待返回
            infoFuture1.get();
            System.out.println(infoFuture1.get());
        } catch (Exception e) {
            e.printStackTrace();
        }

        CompletableFuture<Void> infoFuture2 = CompletableFuture.runAsync(() -> {
            System.out.println("infoFuture2");
            //1、sku基本信息的获取  pms_sku_info
        }, THREAD_POOL_EXECUTOR);


    }

    /**
     * 常用:
     * thenApplyAsync 表示某个任务执行完成后执行的动作,即回调方法,会将该任务的执行结果即方法返回值作为入参传递到回调方法中,测试用例如下:
     */
    public static void Test2() throws ExecutionException, InterruptedException {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread() + " start job1,time->" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread() + " exit job1,time->" + System.currentTimeMillis());
            return 1.2;
        }, THREAD_POOL_EXECUTOR);
        //cf关联的异步任务的返回值作为方法入参,传入到thenApply的方法中

        //thenApplyAsync这里实际创建了一个新的CompletableFuture实例
        CompletableFuture<String> cf2 = cf.thenApplyAsync((result) -> {
            System.out.println(Thread.currentThread() + " start job2,time->" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread() + " exit job2,time->" + System.currentTimeMillis());
            return "test:" + result;
        }, THREAD_POOL_EXECUTOR);

        System.out.println("main thread start cf.get(),time->" + System.currentTimeMillis());
        //等待子任务执行完成
        System.out.println("run result->" + cf.get());
        System.out.println("main thread start cf2.get(),time->" + System.currentTimeMillis());
        System.out.println("run result->" + cf2.get());
        System.out.println("main thread exit,time->" + System.currentTimeMillis());


    }

    /**
     * exceptionally
     * exceptionally方法指定某个任务执行异常时执行的回调方法,会将抛出异常作为参数传递到回调方法中,
     * 如果该任务正常执行则会exceptionally方法返回的CompletionStage的result就是该任务正常执行的结果,测试用例如下:
     *
     * @throws Exception
     */
    public static void Test3() throws Exception {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread() + "job1 start,time->" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            if (true) {
                throw new RuntimeException("test");
            } else {
                System.out.println(Thread.currentThread() + "job1 exit,time->" + System.currentTimeMillis());
                return 1.2;
            }
        }, THREAD_POOL_EXECUTOR);
        //cf执行异常时,将抛出的异常作为入参传递给回调方法
        CompletableFuture<Double> cf2 = cf.exceptionally((param) -> {
            System.out.println(Thread.currentThread() + " start,time->" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println("error stack trace->");
            param.printStackTrace();
            System.out.println(Thread.currentThread() + " exit,time->" + System.currentTimeMillis());
            return -1.1;
        });
        //cf正常执行时执行的逻辑,如果执行异常则不调用此逻辑
        CompletableFuture cf3 = cf.thenAccept((param) -> {
            System.out.println(Thread.currentThread() + "job2 start,time->" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println("param->" + param);
            System.out.println(Thread.currentThread() + "job2 exit,time->" + System.currentTimeMillis());
        });
        System.out.println("main thread start,time->" + System.currentTimeMillis());
        //等待子任务执行完成,此处无论是job2和job3都可以实现job2退出,主线程才退出,如果是cf,则主线程不会等待job2执行完成自动退出了
        //cf2.get时,没有异常,但是依然有返回值,就是cf的返回值
        System.out.println("run result->" + cf2.get());
        System.out.println("main thread exit,time->" + System.currentTimeMillis());
    }

    /**
     * allOf返回的CompletableFuture是多个任务都执行完成后才会执行,只有有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。
     */
    public static void Test4() throws Exception {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread() + " start job1,time->" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread() + " exit job1,time->" + System.currentTimeMillis());
            return 1.2;
        });
        CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread() + " start job2,time->" + System.currentTimeMillis());
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread() + " exit job2,time->" + System.currentTimeMillis());
            return 3.2;
        });
        CompletableFuture<Double> cf3 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread() + " start job3,time->" + System.currentTimeMillis());
            try {
                Thread.sleep(1300);
            } catch (InterruptedException e) {
            }
            //throw new RuntimeException("test");
            System.out.println(Thread.currentThread() + " exit job3,time->" + System.currentTimeMillis());
            return 2.2;
        });
        //allof等待所有任务执行完成才执行cf4,如果有一个任务异常终止,则cf4.get时会抛出异常,都是正常执行,cf4.get返回null
        //anyOf是只有一个任务执行完成,无论是正常执行或者执行异常,都会执行cf4,cf4.get的结果就是已执行完成的任务的执行结果
        CompletableFuture cf4 = CompletableFuture.allOf(cf, cf2, cf3).whenComplete((a, b) -> {
            if (b != null) {
                System.out.println("error stack trace->");
                b.printStackTrace();
            } else {
                System.out.println("run succ,result->" + a);
            }
        });

        System.out.println("main thread start cf4.get(),time->" + System.currentTimeMillis());
        //等待子任务执行完成
        System.out.println("cf4 run result->" + cf4.get());
        System.out.println("main thread exit,time->" + System.currentTimeMillis());
    }

    public static void Test5() {
        //线程池
        ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(5, 16, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        ArrayList<String> A = new ArrayList<>();
        // 创建异步执行任务:
        CompletableFuture<String> B = CompletableFuture.supplyAsync(() -> {
            A.add("B");
            //B返回
            return "B";
        }, THREAD_POOL_EXECUTOR);
        //thenApplyAsync:有返回值
        //thenAcceptAsync:无返回值
        CompletableFuture<String> C = B.thenApplyAsync((result) -> {
            //这里需要B的结果做些操作
            String c = result + "C";
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            A.add(c);
            return c;
        }, THREAD_POOL_EXECUTOR);

        CompletableFuture<String> D = B.thenApplyAsync((result) -> {
            //这里需要B的结果做些操作
            String d = result + "D";
            A.add(d);
            return d;
        }, THREAD_POOL_EXECUTOR);

        try {
            CompletableFuture.allOf(D, C).get();
            System.out.println(A);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

参考:

CompletableFuture使用详解_sermonlizhi的博客-CSDN博客_completablefuture

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