Future系列(CompletableFuture的使用)

1.创建CompletableFuture对象

CompletableFuture提供了四个静态方法用来创建CompletableFuture对象:

public static CompletableFuture   runAsync(Runnable runnable)
public static CompletableFuture   runAsync(Runnable runnable, Executor executor)
public static  CompletableFuture  supplyAsync(Supplier supplier)
public static  CompletableFuture  supplyAsync(Supplier supplier, Executor executor)

Asynsc表示异步,而supplyAsync与runAsync不同在与前者异步返回一个结果,后者是void.第二个函数第二个参数表示是用我们自己创建的线程池,否则采用默认的ForkJoinPool.commonPool()作为它的线程池

        CompletableFuture future = CompletableFuture
                .supplyAsync(() -> {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return Thread.currentThread().getName();
                });
        System.out.println(future.get());//输出ForkJoinPool.commonPool-worker-1

2.计算结果

public T    get()
public T    get(long timeout, TimeUnit unit)
public T    getNow(T valueIfAbsent)
public T    join()

getNow有点特殊,如果结果已经计算完则返回结果或者抛出异常,否则返回给定的valueIfAbsent值。
join()与get()区别在于join()返回计算的结果或者抛出一个unchecked异常(CompletionException),而get()返回一个具体的异常.

3.主动触发计算

public boolean complete(T  value)
public boolean completeExceptionally(Throwable ex)

上面方法表示当调用CompletableFuture.get()被阻塞的时候,那么这个方法就是结束阻塞,并且get()获取设置的value.

        CompletableFuture future = CompletableFuture
                .supplyAsync(() -> {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return Thread.currentThread().getName();
                });
        
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                try {
                    Thread.sleep(1500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                future.complete("hello");
            }
        }).start();
        
        System.out.println(future.get());

上面的例子,如果sleep小于1000,输出hello,大于1000ms,则输出ForkJoinPool.commonPool-worker-1

4.值转化

public  CompletableFuture     thenApply(Function fn)
public  CompletableFuture     thenApplyAsync(Function fn)
public  CompletableFuture     thenApplyAsync(Function fn, Executor executor)

可以通过Function转化数据类型。直接上示例代码

        CompletableFuture future = CompletableFuture
                .supplyAsync(() -> {
                    System.out.println("supplyAsync" + Thread.currentThread().getName());
                    return "step1";
                }).thenApply(new Function() {
                    @Override
                    public String apply(String t) {
                        System.out.println("thenApply" + Thread.currentThread().getName());
                        return "step2";
                    }
                    
                }).thenApplyAsync(new Function() {
                    @Override
                    public String apply(String t) {
                        System.out.println("thenApplyAsync" + Thread.currentThread().getName());
                        return "step3";
                    }
                    
                });
        System.out.println(future.get());

输出

supplyAsyncForkJoinPool.commonPool-worker-1
thenApplymain
thenApplyAsyncForkJoinPool.commonPool-worker-1
step3

thenApply会自动从默认的子线程中切换成主线程

5.消费处理结果

public CompletionStage thenAccept(Consumer action);
public CompletionStage thenAcceptAsync(Consumer action);
public CompletionStage thenAcceptAsync(Consumer action,Executor executor);

注意没有返回值,一般作为最后一步来做。示例代码

        CompletableFuture future = CompletableFuture
                .supplyAsync(() -> {
                    System.out.println("supplyAsync" + Thread.currentThread().getName());
                    return "step1";
                }).thenApply(new Function() {
                    @Override
                    public String apply(String t) {
                        System.out.println("thenApply" + Thread.currentThread().getName());
                        return "step2";
                    }
                    
                }).thenAccept(new Consumer() {
                    @Override
                    public void accept(String t) {
                        System.out.println("accept" + Thread.currentThread().getName());
                    }
                });
        System.out.println(future.get());

输出

supplyAsyncForkJoinPool.commonPool-worker-1
thenApplymain
acceptmain
null

如果换成 thenAcceptAsync,那么就会打印 ForkJoinPool.commonPool-worker-1

6.thenRun 方法

public CompletionStage thenRun(Runnable action);
public CompletionStage thenRunAsync(Runnable action);
public CompletionStage thenRunAsync(Runnable action,Executor executor);

它只是接着上面继续往下运行

        CompletableFuture future = CompletableFuture
                .supplyAsync(() -> {
                    System.out.println("supplyAsync" + Thread.currentThread().getName());
                    return "step1";
                }).thenApply(new Function() {
                    @Override
                    public String apply(String t) {
                        System.out.println("thenApply" + Thread.currentThread().getName());
                        return "step2";
                    }
                    
                }).thenRunAsync(new Runnable() {
                    
                    @Override
                    public void run() {
                        System.out.println("thenRunAsync" + Thread.currentThread().getName());
                    }
                });
        System.out.println(future.get());

输出

supplyAsyncForkJoinPool.commonPool-worker-1
thenApplymain
thenRunAsyncForkJoinPool.commonPool-worker-1
null

如果改成thenRun,就是main

7.合并任务系列

public  CompletionStage thenCombine(CompletionStage other,BiFunction fn);
public  CompletionStage thenCombineAsync(CompletionStage other,BiFunction fn);
public  CompletionStage thenCombineAsync(CompletionStage other,BiFunction fn,Executor executor);

public  CompletionStage thenAcceptBoth(CompletionStage other,BiConsumer action);
public  CompletionStage thenAcceptBothAsync(CompletionStage other,BiConsumer action);
public  CompletionStage thenAcceptBothAsync(CompletionStage other,BiConsumer action,     Executor executor);

当两个CompletionStage都执行完成后,把结果一块处理。thenAcceptBoth 系列没有返回值。还有后面的 runAfterBoth 系列的也是同样的功能

        CompletableFuture future = CompletableFuture
                .supplyAsync(() -> {
                    System.out.println("supplyAsync" + Thread.currentThread().getName());
                    return "step1";
                }).thenApply(new Function() {
                    @Override
                    public String apply(String t) {
                        System.out.println("thenApply" + Thread.currentThread().getName());
                        return "step2";
                    }
                    
                });
        
        CompletableFuture future2 = CompletableFuture
                .supplyAsync(() -> {
                    return "future2-step1";
                }).thenApplyAsync(new Function() {
                    @Override
                    public String apply(String t) {
                        return "future2-step2";
                    }
                    
                });
        
        future.thenCombine(future2, new BiFunction() {

            @Override
            public String apply(String t, String u) {
                System.out.println("thenCombine" + Thread.currentThread().getName());
                return "thenCombine";
            }
            
        });
        
        System.out.println(future.get());

输出

supplyAsyncForkJoinPool.commonPool-worker-1
thenApplymain
thenCombinemain
step2

8.either系列

两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的转化操作。

public  CompletionStage applyToEither(CompletionStage other,Function fn);
public  CompletionStage applyToEitherAsync(CompletionStage other,Function fn);
public  CompletionStage applyToEitherAsync(CompletionStage other,Function fn,Executor executor);

例子我就不写了

9.thenCompose

thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。

public  CompletableFuture thenCompose(Function> fn);
public  CompletableFuture thenComposeAsync(Function> fn) ;
public  CompletableFuture thenComposeAsync(Function> fn, Executor executor) ;

直接上代码

        CompletableFuture future = CompletableFuture.supplyAsync(
                () -> {
                    System.out.println("supplyAsync" + Thread.currentThread().getName());
                    return "step1";
                }).thenCompose(new Function>() {

            @Override
            public CompletionStage apply(String t) {

                return CompletableFuture.supplyAsync(() -> {
                    return "future2-step1";
                });
            }
        });

        System.out.println(future.get());

输出

supplyAsyncForkJoinPool.commonPool-worker-1
future2-step1

感觉和前面的没啥区别呀

10.whenComplete

计算结果完成时的处理

public CompletableFuture     whenComplete(BiConsumer action)
public CompletableFuture     whenCompleteAsync(BiConsumer action)
public CompletableFuture     whenCompleteAsync(BiConsumer action, Executor executor)
public CompletableFuture     exceptionally(Function fn)

直接上代码

        CompletableFuture future = CompletableFuture
                .supplyAsync(() -> {
                    double a = 1/0;
                    return "step1";
                }).whenComplete(new BiConsumer() {

                    @Override
                    public void accept(String t, Throwable throwable) {
                        System.out.println("t = " + t + ", throwable = " + throwable);
                    }
                    
                });

        System.out.println(future.get());

输出

t = null, throwable = java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
    at java.util.concurrent.CompletableFuture.reportGet(Unknown Source)
    at java.util.concurrent.CompletableFuture.get(Unknown Source)
    at completableFuture.Main.main(Main.java:28)
Caused by: java.lang.ArithmeticException: / by zero
    at completableFuture.Main.lambda$0(Main.java:17)
    at java.util.concurrent.CompletableFuture$AsyncSupply.run(Unknown Source)
    at java.util.concurrent.CompletableFuture$AsyncSupply.exec(Unknown Source)
    at java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(Unknown Source)
    at java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
    at java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)

可以看到其实就算accept,整个程序依然会崩溃

11.handle

功能和上面一点一样,计算结果完成时的处理

        CompletableFuture future = CompletableFuture
                .supplyAsync(() -> {
                    double a = 1/0;
                    return "step1";
                }).handle(new BiFunction() {

                    @Override
                    public String apply(String t, Throwable throwable) {
                        System.out.println("t = " + t + ", throwable = " + throwable);
                        return "handle return";
                    }
                });

        System.out.println(future.get());

输出

t = null, throwable = java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
handle return

明显看到程序并没有崩溃,也就是说handle里面把崩溃捕捉了

你可能感兴趣的:(Future系列(CompletableFuture的使用))