【视频笔记】CompletableFuture功能究竟有多强?Spring底层全在用它?CompletableFuture才是并发编程的正确打开方式!

Future的get方法会阻塞
CompletableFuture,可以组合多个异步任务
如可以拿到异步任务中最快的一个,传统异步编程是很麻烦的
如可以在一个任务执行完以后,去执行另一个任务,传统方式是join或嵌套任务(可能回调地狱)
CompletableFuture提供了异步回调来处理

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CompletableFutureTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(2000L);
                return "future task finished";
            }
        });
        new Thread(futureTask).start();
        // 阻塞执行
        System.out.println(futureTask.get());

        System.out.println("main execute finished");
    }
}

-----
future task finished
main execute finished

CompletableFuture 异步执行:
runAsync()方法执行任务是没有返回值的
supplyAsync()方法执行任务则支持返回值

    public static void completableFutureTask() {
        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
            System.out.println("runAsync finished, no response data");
        });

        CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("supplyAsync finished, response hahaha ");
            return "hahaha";
        });
        System.out.println(supplyAsync.join());
    }

组合处理
anyOf 返回跑的最快的那个future。最快的如果异常都玩完
allOf 全部并行执行,如果需要获得返回值,需要配合thenApply, 异常会抛出,不影响其他任务

        CompletableFuture<Object> futureA = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000L);
                System.out.println("A has finished");
                return "A has finished";
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        CompletableFuture<Object> futureB = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(500L);
                System.out.println("B has finished");
                return "B has finished";
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        CompletableFuture<Object> anyFutures = CompletableFuture.anyOf(futureA, futureB);
        System.out.println(anyFutures.join());

    }

上面任务B较快执行完,如果B异常,则整体结果异常

CompletableFuture<Object> futureB = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500L);
throw new RuntimeException("B error");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});

Exception in thread "main" java.util.concurrent.CompletionException: java.lang.RuntimeException: B error at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1770) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) Caused by: java.lang.RuntimeException: B error at com.rocky.CompletableFutureTest.lambda$completableFutureAnyOf$3(CompletableFutureTest.java:54) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ... 6 more

allOf

public static void completableFutureAllOf() throws ExecutionException, InterruptedException {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000L);
                return "A has finished";
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000L);
                return "B has finished";
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        CompletableFuture<String> future = CompletableFuture.allOf(futureA, futureB).thenApply(res -> {
            return futureA.join() + " " + futureB.join();
        });
        System.out.println(future.get());
    }

CompletableFuture的thenCompose和thenApply有什么区别?

参考:CompletableFuture的thenCompose和thenApply有什么区别?CompletableFutu - 掘金

 

异步回调
whenComplete() 没有返回值,且返回的CompletableFuture为任务结果,而非回调结果
handle() 有返回值,且返回的CompletableFuture为回调结果
链式处理
thenRun(Runnable runnable)对异步任务的结果进行操作,不能传入参,也没有返回值。不会阻塞主线程
thenAccept(Consumer consumer) 可传入参数
thenApply(Function function) 可传入参数,并返回结果

thenRun

  public static void completableFutureThenRun(){
        CompletableFuture<Void> supplyAsyncFinished = CompletableFuture.supplyAsync(() -> {
            System.out.println("supplyAsync finished");// 这里是异步执行,主线程之外
            return "supplyAsync result";
        }).thenRun(() -> {
            System.out.println("cannot get supplyAsync result, thenRun finished");
        }).thenRun(() -> {
            System.out.println("cannot get supplyAsync result, thenRun2 finished");
        });
        System.out.println("主线程");
        supplyAsyncFinished.join();
    }

thenAccept

    public static void completableFutureThenAccept(){
        CompletableFuture<Void> supplyAsyncFinished = CompletableFuture.supplyAsync(() -> {
            System.out.println("supplyAsync finished");
            return 5;
        }).thenAccept(num -> {
            System.out.println("can get supplyAsync result" +num * 4);
        });
        System.out.println("主线程");
        supplyAsyncFinished.join();
    }

thenApply

    public static void completableFutureThenApply() {
        CompletableFuture<Integer> supplyAsyncFinished = CompletableFuture.supplyAsync(() -> {
                    System.out.println("supplyAsync finished");
                    return 5;
                }).thenApply(res -> res * 5) //用到上一步的结果
                .thenApply(res -> res + 3);
        System.out.println("主线程");
        System.out.println(supplyAsyncFinished.join());
    }

上面链式方法,出现异常,后面的任务会中断
处理任务重感知不到异常
异常会通过get抛出到主线程

whenComplete

    public static void completableFutureWhenComplete() {
        CompletableFuture<Integer> supplyAsyncFinished = CompletableFuture.supplyAsync(() -> {
            System.out.println("supplyAsync finished");
            return 5 / 0;
        }).whenComplete((res, throwable) -> {
            System.out.println("exec whenComplete method, and print execption msg:"+throwable.getMessage());
        });
        System.out.println("主线程");
        System.out.println(supplyAsyncFinished.join());
    }

 

参考:CompletableFuture功能究竟有多强?Spring底层全在用它?CompletableFuture才是并发编程的正确打开方式!_哔哩哔哩_bilibili

posted @ 2025-05-26 17:11  fanblog  阅读(13)  评论(0)    收藏  举报