java8之CompletableFuture

参考一篇写的非常好的博客戳这里

一、背景

JDK1.5中对线程获取结果进行了很大的优化,具体可以参考我以前的博客戳这里,但是针对多线程结果其实还是通过无限循环,或者 阻塞的方式来获取的,很不友好,比如Rxjava已经实现了利用观察者模式,完成后通过回调来获取结果。所以在jdk1.8中增加了类CompletableFuture来对Future进行增强。

二、简单实用

2.1、创建异步应用

CompletableFuture.supplyAsync(()->{
            sleep(60000);
            System.out.println("线程:"+Thread.currentThread().getName()+"调用了supplyAsync");
            return "zhw";
 })

利用函数式编程来实现或比较简单、明了。supplyAsync内部中自动创建一个线程池。当然你可以可以指定线程池。

下面是默认线程池的代码:

/**
     * Default executor -- ForkJoinPool.commonPool() unless it cannot
     * support parallelism.
     */
    private static final Executor asyncPool = useCommonPool ?
        ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();

利用jdk1.7中的ForkJoinPool线程池来执行任务,无需关系线程池的创建和销毁,只需关系具体的业务,增加了开发效率。

runAsyn也可以完成创建,不过参数不同,还是supplyAsync更实用

public static CompletableFuture 	runAsync(Runnable runnable)
public static CompletableFuture 	runAsync(Runnable runnable, Executor executor)

特点:

  • 如果以Async结尾的方法,都是另起一个新线程异步执行。否则都是和上个调用在同一个线程中执行,适用于大部分方法,必须下面的Apply、Accept、whenComplete方法等等

2.2、Apply对结果进一步处理

supplyAsync方法和CompletableFuture里面大多方法都是返回一个新的CompletableFuture引用,这是链式调用的基础

 CompletableFuture.supplyAsync(()->{
            sleep(60000);
            System.out.println("线程:"+Thread.currentThread().getName()+"调用了supplyAsync");
            return "zhw";
        }).thenApplyAsync(x->{
            System.out.println("线程:"+Thread.currentThread().getName()+"调用了thenApply");
            return x+" hellow word";
        });

比如thenApplyAsync,这个方法从字面看出另起一个线程,thenApply就是同步调用。
上面中apply中的方法都是利用上面的结果作为入参,然后对结果再次处理加工,比如supplyAsync返回"zhw",然后在thenApplyAsync方法中"zhw"作为参数传入,这样上面整个结果就是"zhw hellow word".

下面是我的总结

CompletableFuture中方法 函数式接口
Apply Function

2.3、Accept对结果纯消费

他和Apply方法的不同就是更新consumer

CompletableFuture中方法 函数式接口
Apply Consumer

上个链式的结果都是Apply、accept方法的入参。

2.4、whenComplete获取结果

  public static void testWhenComplete() throws Exception{

        CompletableFuture future = CompletableFuture.supplyAsync(BasicMain::getMoreData);
        Future f = future.whenComplete((v, e) -> {
            System.out.println(v);
            System.out.println(e);
        });
        System.out.println(f.get());
    }

whenComplete有两个参数,第一个是正常的结果,第二个e是异常。其中还有handle方法,这个其实就是whenComplete+Apply,两个方法的组合


2.5、结果联合

两个不想干的方法调用,可以同时开始,然后在将两个结果进行合并返回

 CompletableFuture
                .supplyAsync(()->{
                    log.debug("supplyAsync1");
                    sleep(2000);
                    return "zhw";
                })
                .thenCombineAsync(CompletableFuture.supplyAsync(()->{
                    log.debug("supplyAsync2");
                    sleep(2000);
                    return " hellow ";
                }),(s1,s2)->{
                    log.debug("thenCombineAsync");
                    return s1+s2;
                })

比如上面两个方法各自需要2s,如果同步处理需要4s结束,但是这样处理后只需要2s就返回结果。
目前也只看到两个结果进行联合,感觉还是有限制,不如Rxjava方便

你可能感兴趣的:(多线程)