Java8 增强的Future:CompletableFuture

     CompletableFuture是Java8新增的一个超大型工具类,为什么说她大呢?因为一方面它实现了Future接口,更重要的是,它实现了CompletionStage接口.这个接口也是Java8新增加的,而CompletionStage拥有多达约40种方法,

	* 完成了通知我
	* 异步执行任务

通过CompletableFuture提供进一步封装,我们很容易实现Future模式那样的异步调用,例如:
public static Integer cale(Integer para) {
    try {
        Thread.sleep(1000);

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return para * para;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {

    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> cale(50));
    System.out.println(future.get());
}

上述代码中CompletableFuture.supplyAsync()方法构造了一个CompletableFuture实例,在supplyAsync()函数中,他会在一个新的线程中,执行传入的参数.在这里,,他会执行calc()方法,而calc()方法的执行可能是比较慢的,但是不影响CompletableFuture实例的构造速度,因此supplyAsync()会立即返回,他返回的CompletableFuture对象实例就可以作为这次调用的契约,在将来任何场合,用于获得最终的计算结果.
在CompletableFuture中,类似的工厂方法有以下几个:
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                   Executor executor)
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,
                                               Executor executor)

     其中supplyAsync()方法用于那些需要返回值的场景,比如计算某个数据,而runAsync()方法用于没有返回值的场景,比如,仅仅是简单地执行某一个异步动作.
     在这两对方法中,都有一个方法可以接手一个Executor参数,这使我们可以让Supplier<U>或者Runnable在指定的线程池工作,如果不指定,则在默认的系统公共的ForkJoinPool.common线程池中执行.

	* 流式调用

在前文中我已经简单的提到,CompletionStage的约40个接口为函数式编程做准备的,在这里,就让我们看一下,如果使用这些接口进行函数式的流式API调用:
CompletableFuture<Void> future = CompletableFuture
        .supplyAsync(() -> cale(50))
        .thenApply(i -> Integer.toString(i))
        .thenApply(str -> "\"" + str + "\"")
        .thenAccept(System.out::println);
future.get();

     上述代码中,使用supplyAsync()函数执行了一个异步任务,接着连续使用流式调用对任务处理结果进行在加工,直到最后的结果输出:

	* CompletableFuture中的异常处理

CompletableFuture<Void> future = CompletableFuture
        .supplyAsync(() -> cale(50))
        .exceptionally(ex -> {
            System.out.println("ex.toString() = " + ex.toString());
            return 0;
        })
        .thenApply(i -> Integer.toString(i))
        .thenApply(str -> "\"" + str + "\"")
        .thenAccept(System.out::println);
future.get();

	* 组合多个CompletableFuture

CompletableFuture还允许你将多个CompletableFuture进行组合,一种方法是使用thenCompose(),它的签名如下:
public <U> CompletableFuture<U> thenCompose(
    Function<? super T, ? extends CompletionStage<U>> fn)

一个CompletableFuture可以执行完成后,将执行结果通过Function传递给下一个CompletionStage进行处理:

CompletableFuture<Void> future = CompletableFuture
        .supplyAsync(() -> cale(50))
        .thenCompose(i -> CompletableFuture
                .supplyAsync(() -> cale(i)))
        .thenApply(i -> Integer.toString(i))
        .thenApply(str -> "\"" + str + "\"")
        .thenAccept(System.out::println);
future.get();

另外一种组和多个CompletableFuture的方法是thenCombine(),它的签名如下:
public <U,V> CompletableFuture<V> thenCombine(
    CompletionStage<? extends U> other,
    BiFunction<? super T,? super U,? extends V> fn)

     方法thenCombine()首先完成当前CompletableFuture和other的执行,接着,将这两者的执行结果传递给BiFunction(该接口接受两个参数,并有一个返回值),并返回代表BiFuntion实例的CompletableFuture对象:
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> cale(50));
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> cale(25));

CompletableFuture<Void> fu = future1.thenCombine(future2, (i, j) -> (i + j))
        .thenApply(str -> "\"" + str + "\"")
        .thenAccept(System.out::println);
fu.get();

  

时间: 2024-08-11 09:08:09

Java8 增强的Future:CompletableFuture的相关文章

Java8 增强工具类 Arrays 笔记

随手笔记做Arrays工具类分为两类单线程和多线程 以下所有带有下标范围限定的,都为含头不含尾 单线程:1.binarySearch:查找数组中为 key 的 下标 :binarySearch 二分法查找,数组必须有序,且存在此数组中,否则返回负数下标 Arrays.binarySearch(Object[] a,Object key):intArrays.binarySearch(Object[] a, int fromIndex, int toIndex,Object key):int跳至例

java8 增强的Iterator遍历集合元素

Iterator接口也是Java集合框架的成员,与Collection和Map两个系列的集合不一样的是Collection和Map系列主要用于充当容器的作用,而Iterator正如其名字一样是主要用于迭代访问Collection集合中的元素,Iterator对象也被称为迭代器. Iterator接口里面定义了下面4个方法: >boolean hasNext():如果被迭代遍历的集合还没有被遍历完,返回True >Object next():返回集合里面的下一个元素 >remove():删

Java8增强的Map集合

Map集合简介 Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另外一组用于保存Map里的vlaue,key和value都可以是任何引用类型的数据. Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false. key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的.确定的value.从Map中取出数据时,只要给出指定的key,就可以取出对应的value. 如果把Map里的所有key

java(java8 CompletableFuture)异步执行之后获取回调

应用场景是产品中需要有一个批量执行的任务,很多店铺同时执行,并且需要执行之后的结果进行业务处理,然后在全部执行完毕之后通知处理完毕 用Future和Callable虽然可以阻塞获取结果,但是因为处理起来有些繁琐,比较消耗资源,而CompletableFuture可以满足这个需求,让异步编程变的更加轻松. 直接上demo public static void main(String[] args) { //批量异步 ExecutorService executor = Executors.newF

Future和CompletableFuture

Future 从JDK1.5开始,提供了Future来表示异步计算的结果,一般它需要结合ExecutorService(执行者)和Callable(任务)来使用. 示例 import java.util.*; import java.util.concurrent.*; public class Main { public static void main(String[] args) throws Exception { ThreadPoolExecutor executor = new Th

Java CompletableFuture 详解

Future是Java 5添加的类,用来描述一个异步计算的结果.你可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算完成返回结果,你也可以使用cancel方法停止任务的执行. public class BasicFuture { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService es = Executors.

Transform java future into completable future

Future is introduced in JDK 1.5 by Doug Lea to represent "the result of an asynchronous computation". ExecutorService exe = Executors.newCachedThreadPool(); Runnable runnable = () -> System.out.println("Runnable"); Callable<Strin

从Java future 到 Guava ListenableFuture实现异步调用

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/51232004 前言 随着移动互联网的蓬勃发展,手机App层出不穷,其业务也随之变得错综复杂.针对于开发人员来说,可能之前的一个业务只需要调取一次第三方接口以获取数据,而如今随着需求的增加,该业务需调取多个不同的第三方接口.通常,我们处理方法是让代码同步顺序的去调取这些接口.显然,调取接口数量的增加必然会造成响应时间的增加,势必会对系统性能造成一定影响. 为

从Java Future到Guava ListenableFuture实现异步调用

原文地址: http://blog.csdn.net/pistolove/article/details/51232004 Java Future ????通过Executors可以创建不同类似的线程池,常见的大概有下表几种类型,还有些可能为被列出.在实际应用中,个人感觉主要使用newCachedThreadPook和newFixedThreadPool来创建线程池. Executors创建线程池源码 //调用newCachedThreadPool方法,可以创建一个缓冲型线程池,而在改方法中通过