Future is introduced in JDK 1.5 by Doug Lea to represent "the result of an asynchronous computation".

Java 5中引入了Future接口,用于代表异步计算的结果

        ExecutorService exe = Executors.newCachedThreadPool();
        Runnable runnable = () -> System.out.println("Runnable");
        Callable<String> callable = () -> "Callable";
        exe.submit(runnable);
        Future<String> futureResult = exe.submit(callable);
        String result = futureResult.get();
        System.out.println(result);
        exe.shutdown();

Similar to runnable, callable can also be submitted to executor service. Differently, callable is "A task that returns a result and may throw an exception."

The call to get a future result lead current thread to wait "if necessary for the computation to complete, and then retrieves its result." Below is one implementation of get method.

同时还引入了Callable接口来代表有返回值的任务,把 callable提交给线程池便可以获得一个future。

当我们想要获取callable的结果,或者说想要拿到future的值,可能会需要适时的等待。参照ForkjoinPool中对Future get的实现,基本可以明白,当前线程会一直等到future所代表的异步任务执行完毕。

    public final V get() throws InterruptedException, ExecutionException {
        int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
            doJoin() : externalInterruptibleAwaitDone();
        Throwable ex;
        if ((s &= DONE_MASK) == CANCELLED)
            throw new CancellationException();
        if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
            throw new ExecutionException(ex);
        return getRawResult();
    }

In JDK 1.8, another future, CompletableFuture, is introduced by the same author with epoch-making significance. Completable future is "A {@link Future} that may be explicitly completed (setting its value and status), and may be used as a {@link CompletionStage}, supporting dependent functions and actions that trigger upon its completion."

Java 8中,Doug Lea大神又引入了CompletableFuture 这一大作,既拥有future的特性,同时又可以根据任务的完成状态来触发后续的动作,以一种可同步可异步的调用链方式来执行更为复杂的任务。

Now it comes to the interesting part. Hey, what if we want to convert the legacy future into completable future so as to make full use of the new features?

Well, let's see a snippet from stack overflow http://stackoverflow.com/questions/23301598/transform-java-future-into-a-completablefuture

现在问题来了,假如我们想要把老代码中的 future 转换成 completable future,怎么做比较好呢?如果第三方库本身拥有完成和失败的回调,整合completable future 还相对容易,就像下面这个从stack overflow搬来的例子一样:

    AsynchronousFileChannel open = AsynchronousFileChannel.open(Paths.get("/some/file"));
    // ...
    CompletableFuture<ByteBuffer> completableFuture = new CompletableFuture<ByteBuffer>();
    open.read(buffer, position, null, new CompletionHandler<Integer, Void>() {
        @Override
        public void completed(Integer result, Void attachment) {
            completableFuture.complete(buffer);
        }

        @Override
        public void failed(Throwable exc, Void attachment) {
            completableFuture.completeExceptionally(exc);
        }
    });
    completableFuture.thenApply(...)

If the 3rd party library support complete and fail callback, it's convinient to integrate with completable future. But usually, future inteferface won't contain these methods.

Hmmm, feels so close... and unreachable. Wait, how about ListenableFuture introduced by Guava ? It can add callbacks for a future.

然而。。。通常的future接口并没有这些方法╮( ̄▽ ̄")╭ 别急,俗话说,车到山前必有路,让我们回想回想Guava所引入的ListenableFuture, 它可以给future 增加完成和失败的回调。

ListeningExecutorService executor1 = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = executor1.submit(new Callable<Explosion>() {
  public Explosion call() {
    return pushBigRedButton();
  }
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
  // we want this handler to run immediately after we push the big red button!
  public void onSuccess(Explosion explosion) {
    walkAwayFrom(explosion);
  }
  public void onFailure(Throwable thrown) {
    battleArchNemesis(); // escaped the explosion!
  }
}, executor2);

Pattern matched, problem solved, and everyone is happy now.

Do care about executor1 and executor2, configure the thread pools properly will boost app performance, cheers~

看到熟悉的模型,问题迎刃而解。

注意下上面例子中的executor1 和 executor2,实际运用的时候合理的调节线程池的参数可以更好的提升应用性能。

Transform java future into completable future 【将 future 转成 completable future】的更多相关文章

  1. java并发:获取线程执行结果(Callable、Future、FutureTask)

    初识Callable and Future 在编码时,我们可以通过继承Thread或是实现Runnable接口来创建线程,但是这两种方式都存在一个缺陷:在执行完任务之后无法获取执行结果.如果需要获取执 ...

  2. Java程序员必须掌握的线程知识-Callable和Future

    Callable和Future出现的原因 创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需 ...

  3. 使用 DJ Java Decompiler 将整个jar包反编译成源文件

    使用 DJ Java Decompiler 将整个jar包反编译成源文件 所使用的软件是 DJ Java Decompiler 3.9. 下面是一个有用的参考文档,说明如何批量编译 http://ww ...

  4. 分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map

    原文:分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map import java.util.Map; import org.apache.commons.lang.Ar ...

  5. 用java将简单的word文档换成pdf文档

    用java将简单的word文档换成pdf文档的方式很多,因为很多都没有实际测试过,所以这里就先泛泛的说一下 整体上来看分两种: 1.纯java代码实现,有很多优秀的开源软件可以用,比如poi,itex ...

  6. 老杜告诉你java小白到大神是怎么炼成的(转载)

    老杜告诉你java小白到大神是怎么炼成的 1. 学习前的准备 一个好的学习方法(应该怎么学习更高效): 一个合格的程序员应该具备两个能力 有一个很好的指法速度(敲代码快) 有一个很好的编程思想(编程思 ...

  7. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  8. Java:多线程,线程池,使用CompletionService通过Future来处理Callable的返回结果

    1. 背景 在Java5的多线程中,可以使用Callable接口来实现具有返回值的线程.使用线程池的submit方法提交Callable任务,利用submit方法返回的Future存根,调用此存根的g ...

  9. java多线程之创建线程的4种方式及Future

    Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例.Java可以用四种方式来创建线程: 继承Thread创建线程 实现Runnable接口创建线程 实现callab ...

随机推荐

  1. SQL注入相关的知识【Mysql为例子】

    以DVWA的sql注入初级为例,结合网上搜索的相关利用方式,总结成这一篇文章,内容会有点跳跃. 大纲: 1.初级手工注入 2.order by的使用 3.union查询注意点 4.Mysql相关的注释 ...

  2. 对VC++6.0爱得深沉(三)静态库的制作与使用

    [创建] 1)建立新工程(win32静态库) (2)加入.h文件于.cpp文件如图. 3)编译-构建,生成.lib文件 [使用] 1)新建普通控制台程序 2)打开项目文件夹与刚才生成的库文件夹 3)方 ...

  3. windows phone 8.1开发SQlite数据库引用安装

    原文出自:http://www.bcmeng.com/windows-phone-sqlite/ windows phone 8.1开发SQlite数据库引用安装 第一步: 安装SQlite forw ...

  4. 头文件limits—各个类型的数据的范围

    要想知道各个类型的数据如int.float.double.long等所能表示的范围,可以加上头文件<limits>,这些类型的范围都在类numeric_limits中定义了的. 类模板:t ...

  5. Ubuntu14.04上安装openGL

    安装命令:sudo apt-get install build-essential sudo apt-get install libgl1-mesa-dev sudo apt-get install ...

  6. Linux-ubuntu安装过程讲解

    前言也不准备介绍Linux是什么,为什么要安装ubuntu?相信你能够看到这篇文章也知道自己想要做什么. 一,准备工具 1.VMwareWorkstation虚拟机 下载地址:https://my.v ...

  7. css的存在方式和选择器

    css的存在方式 元素内联 页面嵌入 外部引入 元素内联 直接在html的标签中定义样式,类似于: <div style="属性1;属性2;属性3"><div&g ...

  8. python混账的编码问题解决之道

    下面的代码作用是修改文件的编码格式.代码很简单,但是也很牛逼(在我看来),这是在segment上找到的解决办法,废话不多说,直接上代码. import codecsdef ReadFile(fileP ...

  9. scipy安装问题

    刚开始使用pip安装的scipy,后来报了错误,具体意思是  numpy版本不支持. 在python.org.pypi 官网上的SciPy包是一个zip版本的,要使用与numpy相对应的后缀才行,也就 ...

  10. [原]C#与非托管——动机

    Unity3D采用C#作为脚本开发语言,本来是可以直接提供代码局部更新机制的,可惜Mono和Unity3D迫于苹果的压力,在iOS上采用AOT模式运行,断绝了代码局部更新的路(任何一个具有很高知名度的 ...