JUC并发编程之:CompletableFuture (七)

JUC并发编程之:CompletableFuture (七)

一、概述

##一、CompletableFuture

1、创建异步操作:
CompletableFuture提供了四种方法来创建异步操作:

=============================================================================================
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
=============================================================================================

其中:没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行

runAsync方法不支持返回值,SupplyAsync支持返回值

【例子:juc5_use包下:CompletableFutureTest】

结论:future.get();会阻塞主线程向下接着执行,等异步执行完成后再向下执行,如果有返回值,其可以得到返回值

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> exceptionally(Function<Throwable,? extends T> fn)
=============================================================================================

从参数可以看到,这里可以处理 "正常的计算结果" 和 "异常情况"

其中:
whenComplete方法是执行当前任务的线程继续执行whenComplete方法,在异步正常/非正常执行完后,都会接着执行 whenComplete
whenCompleteAsync是把whenCompleteAsync这个任务提交给线程池来继续执行

exceptionally: 在异步执行发生异常时,会接着执行exceptionally,用以处理异常的情况

3、线程串行化执行
当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。【第二个任务依赖第一个任务的结果】

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

从参数中可以看到:t为上一个任务返回的结果类型,u为当前任务要返回的结果类型

其中:
thenApply:串行化执行,thenApply方法执行需要依赖supplyAsync的结果时可以使用thenApply
当supplyAsync发生异常时,会直接执行exceptionally或直接抛出异常,不会继续执行thenApply



4、执行完任务对结果的处理
=============================================================================================
public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor);
=============================================================================================

handle 是执行任务完成时对结果的处理。
handle 方法和 thenApply 方法处理方式基本一样。
不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。
thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。

whenComplete接收的是BiConsumer,handler接收的是BiFunction;
BiConsumer是直接消费的,而BiFunction是有返回值的,

5、消费结果处理
接收任务的处理结果,并消费处理,无返回结果。
=============================================================================================
public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor);


public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
=============================================================================================

thenAccept任务正常执行完后,消费上一步的处理结果,无返回值
thenRun任务正常执行完后,不关心且无法处理上一步的处理结果,只要上一步正常执行完后就开始执行thenRun方法,无返回值

6、合并任务:(有返回值)
thenCombine 会把 两个 CompletionStage 的任务都执行完成后,把两个任务的结果一块交给 thenCombine 来处理。
=============================================================================================
public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);
=============================================================================================

thenCombine处理两个completableStage的处理结果,并且返回(有返回值)

7、合并任务:(无返回值)
当两个CompletionStage都执行完成后,把结果一块交给thenAcceptBoth来进行消耗
=============================================================================================
public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,     Executor executor);
=============================================================================================

thenAcceptBoth处理两个completableStage的处理结果(无返回值)

8、两个CompletionStage,谁返回快就用谁的结果进行下一步的操作(有返回值)(可以使用上面的结果)
=============================================================================================
public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor);
=============================================================================================
applyToEither:两个CompletionStage,谁返回快就用谁的结果进行下一步的操作(有返回值)

9、两个CompletableStage,谁返回快就用谁的结果进行下一步的操作(无返回值)(可以使用上面的结果)
=============================================================================================
public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor);
=============================================================================================
acceptEither:两个CompletableStage,谁返回快就用谁的结果进行下一步的操作(无返回值)

10、两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)(无返回值)(不可以使用上面的结果)
=============================================================================================
public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);
=============================================================================================
runAfterEither:两个CompletableStage,任何一个执行完了就可以执行runAferEither里的run方法,无法使用上面的处理结果,且无返回值


11、两个CompletionStage,都完成了计算才会执行下一步的操作(Runnable)(无返回值)(不可以使用上面的结果)
=============================================================================================
public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);
=============================================================================================
runAfterBoth:两个complatableStage,都执行完成了,才能执行runAfterBoth,无法使用上面的处理结果,且无返回值

12、thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。
=============================================================================================
public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) ;
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor) ;
=============================================================================================


二、示例

package com.lee.juc.juc5_use;

import com.lee.base.commons.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.concurrent.*;
import java.util.function.*;

/**
 * 项目名称:basic
 * 类 名 称:CompletableFutureTest
 * 类 描 述:
 * 创建时间:2021-08-26 11:49
 * 创 建 人:Lee
 */
@Slf4j
public class CompletableFutureTest {

    private ExecutorService executorService = Executors.newFixedThreadPool(5);


    /**
     * runAsync无返回值
     * future.get()会阻塞主线程接着向下执行
     */
    @Test
    public void runAsyncTest() throws ExecutionException, InterruptedException {
        log.info("test......start");

        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("run async.......");
        }, executorService);

        future.get();

        log.info("test......end");
    }


    /**
     * applyAsync有返回值
     * future.get()会阻塞祝线程接着向下执行,且可以获取返回值
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void applyAsyncTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        User u = new User(1, "lee", 20);

        CompletableFuture<User> future = CompletableFuture.supplyAsync(() -> {
            log.info("apply async.......");
            return new User(1, "lee", 20);
        }, executorService);

        User user = future.get();
        log.info("test------->result:{}", user);

        log.info("test.......end");
    }


    /**
     * whenComplete:在异步 正常/非正常执行完后,都会接着执行 whenComplete
     * whenComplete:用以继续处理异步正常执行的结果,或异常情况
     * (示例中:r为异步执行的结果,t为异常)
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void whenCompleteTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<User> future = CompletableFuture.supplyAsync(() -> {
            log.info("supply async.......");
            int a = 10 / 0;
            return new User(1, "lee", 20);
        }, executorService).whenComplete((r, t) -> {
            log.info("whenComplete.......");
            r.setAge(18);
            return;
        });

        User user = future.get();
        log.info("test------>result:{}", user);

        log.info("test.......end");
    }


    /**
     * exceptionally: 在异步执行发生异常时,会接着执行exceptionally
     * exceptionally:用以继续处理异常的情况
     * (示例中:t为异常)
     */
    @Test
    public void exceptionallyTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<User> future = CompletableFuture.supplyAsync(() -> {
            log.info("supply async.......");
            int i = 10 / 0;
            return new User(1, "lee", 18);
        }, executorService).exceptionally(t -> {
            log.info("exceptionally.......e:{}", t);
            return null;
        });

        User user = future.get();
        log.info("test.......result:{}", user);

        log.info("test.......end");
    }


    /**
     * thenApply:串行化执行,thenApply方法执行需要依赖supplyAsync的结果时可以使用thenApply
     * 当supplyAsync发生异常时,会直接执行exceptionally或直接抛出异常,不会继续执行thenApply
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void thenApplyTest() throws ExecutionException, InterruptedException {
        log.info("test......start");

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            log.info("supply async.......");
            int i = 10 / 0;
            return 10;
        }, executorService).thenApply(new Function<Integer, String>() {
            @Override
            public String apply(Integer params) {
                log.info("then apply.......");
                return params + " append 5";
            }
        }).exceptionally(t -> {
            log.info("exception deal");
            return null;
        });

        String res = future.get();
        log.info("test.......result:{}", res);

        log.info("test......end");
    }


    /**
     * handle 是执行任务完成时对结果的处理。
     * handle 方法和 thenApply 方法处理方式基本一样。
     * <p>
     * 不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。
     * thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。
     * <p>
     * whenComplete接收的是BiConsumer,handler接收的是BiFunction;
     * BiConsumer是直接消费的,而BiFunction是有返回值的,
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void handleTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            log.info("supply async.......");
            int i = 10 / 0;
            return 10;
        }, executorService).handle(new BiFunction<Integer, Throwable, String>() {
            @Override
            public String apply(Integer params, Throwable throwable) {
                return params + "  append 5";
            }
        }).exceptionally(t -> {
            log.info("exceptionally deal");
            return null;
        });

        String res = future.get();
        log.info("test.......res:{}", res);

        log.info("test.......end");
    }


    /**
     * 任务正常执行完后,消费上一步的处理结果,无返回值
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void thenAcceptTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            log.info("supply async.......");
            //int i = 10 / 0;
            return 10;
        }, executorService).thenAccept(result -> {
            log.info("then accept.......1 " + result);
            if(result==10){
                return;
            }
            log.info("then accept.......2 " + result);
        }).exceptionally(t -> {
            log.info("exceptionally.......");
            return null;
        });

        future.get();

        log.info("test.......end");
    }


    /**
     * 任务正常执行完后,不关心且无法处理上一步的处理结果,
     * 只要上一步正常执行完后就开始执行thenRun方法,无返回值
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void thenRunTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            log.info("supply async.......");
            //int i = 10 / 0;
            return 10;
        }, executorService).thenRun(() -> {

            log.info("then run.......");

        }).exceptionally(t -> {
            log.info("exceptionally.......");
            return null;
        });

        future.get();

        log.info("test.......end");
    }


    /**
     * 处理两个completableStage的处理结果,并且返回(有返回值)
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void thenCombineTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 1 , supply async.......");
            return "future1====>10 ";
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 2 , supply async.......");
            int i = 10 / 0;
            return "future2=====>20 ";
        }, executorService).exceptionally(t -> {
            log.info("future2  exceptionally");
            return "exceptionally====>20";
        });

        CompletableFuture<Object> result = future1.thenCombine(future2, new BiFunction<String, String, Object>() {
            @Override
            public Object apply(String result1, String result2) {
                log.info("");
                return result1 + result2;
            }
        });
        log.info("test.......time test");
        String res = (String) result.get();
        log.info("test.......result:{}", res);

        log.info("test.......end");
    }


    /**
     * 处理两个completableStage的处理结果(无返回值)
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void thenAcceptBothTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 1 , supply async.......");
            return "future1====>10 ";
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 2 , supply async.......");
            int i = 10 / 0;
            return "future2=====>20 ";
        }, executorService).exceptionally(t -> {
            log.info("future2  exceptionally");
            return "exceptionally====>20";
        });

        CompletableFuture<Void> results = future1.thenAcceptBoth(future2, new BiConsumer<String, String>() {
            @Override
            public void accept(String result1, String reuslt2) {
                log.info(result1 + reuslt2);
            }
        });

        results.get();

        log.info("test.......end");
    }


    /**
     * 两个CompletableStage,谁处理快就用谁的结果进行下一步操作,有返回值
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void applyToEitherTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 1 , supply async.......");
            return "future1====>10 ";
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 2 , supply async.......");
            int i = 10 / 0;
            return "future2=====>20 ";
        }, executorService).exceptionally(t -> {
            log.info("future2  exceptionally");
            return "exceptionally====>20";
        });

        CompletableFuture<Object> results = future1.applyToEither(future2, new Function<String, Object>() {
            @Override
            public Object apply(String firstResult) {
                return "谁快就用谁的result:" + firstResult;
            }
        });

        String res = (String) results.get();
        log.info("test.......res:{}", res);

        log.info("test.......end");
    }


    /**
     * 两个CompletableStage,谁处理快就用谁的结果进行下一步处理,无返回值
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void acceptEitherTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 1 , supply async.......");
            return "future1====>10 ";
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 2 , supply async.......");
            int i = 10 / 0;
            return "future2=====>20 ";
        }, executorService).exceptionally(t -> {
            log.info("future2  exceptionally");
            return "exceptionally====>20";
        });

        CompletableFuture<Void> results = future1.acceptEither(future2, new Consumer<String>() {
            @Override
            public void accept(String firstResult) {
                log.info("谁快就用谁的result:" + firstResult);
            }
        });

        results.get();

        log.info("test.......end");
    }


    /**
     * 两个CompletableStage,任何一个执行完了就可以执行runAferEither里的run方法,
     * 无法使用上面的处理结果,且无返回值
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void runAfterEitherTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 1 , supply async.......");
            return "future1====>10 ";
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 2 , supply async.......");
            int i = 10 / 0;
            return "future2=====>20 ";
        }, executorService).exceptionally(t -> {
            log.info("future2  exceptionally");
            return "exceptionally====>20";
        });

        CompletableFuture<Void> result = future1.runAfterEither(future2, new Runnable() {
            @Override
            public void run() {
                log.info("上面任何一个future,执行完就可以执行这里的操作");
            }
        });

        result.get();

        log.info("test.......end");
    }


    /**
     * 两个complatableStage,都执行完成了,才能执行runAfterBoth,无法使用上面的处理结果,且无返回值
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void runAfterBothTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 1 , supply async.......");
            return "future1====>10 ";
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 2 , supply async.......");
            int i = 10 / 0;
            return "future2=====>20 ";
        }, executorService).exceptionally(t -> {
            log.info("future2  exceptionally");
            return "exceptionally====>20";
        });

        CompletableFuture<Void> result = future1.runAfterBoth(future2, new Runnable() {
            @Override
            public void run() {
                log.info("上面两个都处理完成了,才能执行这里");
            }
        });

        result.get();

        log.info("test.......end");
    }


    /**
     * thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void thenComposeTest() throws ExecutionException, InterruptedException {
        log.info("test.......start");

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("future 1 , supply async.......");
            return "future1====>10 ";
        }, executorService).thenCompose(new Function<String, CompletionStage<String>>() {
            @Override
            public CompletionStage<String> apply(String param) {
                return CompletableFuture.supplyAsync(new Supplier<String>() {
                    @Override
                    public String get() {
                        return "deal with res1:" + param + ", return res2";
                    }
                });
            }
        });

        String res = future1.get();
        log.info("test.......result:{}", res);

        log.info("test.......end");

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值