一、Future介绍    

Future
以前我们如果有个方法action执行,比如去数据库中查询数据、上传一个文件等,这个方法执行10分钟,调用者就需要等10分钟。
基于此,调用者可以先执行action,返回一个票据future,然后可以继续做其他的事情,这样就不阻塞了,完全异步化。然后可以根据future拿到action的结果。

自己怎么实现一个Future呢?

代码例子:

 package com.cy.java8;

 import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; public class FutureInAction {
public static void main(String[] args) throws InterruptedException {
Future<String> future = invoke(() -> {
try {
Thread.sleep(10000);
return "I am finished";
} catch (InterruptedException e) {
return "error";
}
}); System.out.println(future.get());
System.out.println(future.get());
System.out.println(future.get());
//do other thing... while (!future.isDone()) {
Thread.sleep(10);
}
System.out.println(future.get());
} /**
* 以前阻塞式的方式
*
* @param callable
* @param <T>
* @return
*/
private static <T> T block(Callable<T> callable) {
return callable.action();
} /**
* Future异步方式
*
* @param callable
* @param <T>
* @return
*/
private static <T> Future<T> invoke(Callable<T> callable) {
AtomicReference<T> result = new AtomicReference<>();
AtomicBoolean finished = new AtomicBoolean(false);
Thread t = new Thread(() -> {
T value = callable.action();
result.set(value);
finished.set(true);
});
t.start(); Future<T> future = new Future<T>() {
@Override
public T get() {
return result.get();
} @Override
public boolean isDone() {
return finished.get();
}
};
return future;
} private interface Future<T> {
T get(); boolean isDone();
} private interface Callable<T> {
T action();
}
}

console打印:

null
null
null
I am finished

二、jdk自带的Future介绍

 package com.cy.java8;

 import java.util.concurrent.*;

 public class FutureInAction2 {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
/**
* 创建了一个线程池,但这个线程池里面只有1根线程,单线程
* 这个线程是可以复用的,它执行完之后不会消失,会始终保持等待另外一个任务去执行
* 所以main函数执行结束之后,它不会退出的,所以还要shutdown
*/
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(() -> {
try {
Thread.sleep(10000);
return "I am finished.";
} catch (InterruptedException e) {
return "I am error.";
}
}); //do other thing... /**
* jdk的future和我们自己写的不一样,它get的时候会阻塞住,如果没有结果它就阻塞住了,一直等结果
*/
//String value = future.get();
//System.out.println(value); //最多等10秒,如果没有拿到结果就拉倒,抛TimeoutException
//String value2 = future.get(10000, TimeUnit.MILLISECONDS);
//System.out.println(value2); while(!future.isDone()){
Thread.sleep(10);
}
System.out.println(future.get()); executorService.shutdown();
}
}

三、CompletableFuture引入

能不能future的任务执行完成之后,你来回调我呢?异步回调,你完成了之后来回调我。
就像ajax的异步回调,post请求完成之后回调函数,来执行其他的东西。
CompletableFuture最大的作用就是干这个的。

在讲CompletableFuture之前,先说下它的原理,自己模拟实现一个CompletableFuture.

模拟代码例子:

 package com.cy.java8;

 import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; public class FutureInAction3 {
public static void main(String[] args) {
invoke(() -> {
try {
Thread.sleep(3000);
return "I am finished.";
} catch (InterruptedException e) {
return "I am error.";
}
}).setCompletable(new Completable<String>() {
@Override
public void complete(String s) {
System.out.println("complete. value = " + s);
} @Override
public void exception(Throwable e) {
System.out.println("error...");
e.printStackTrace();
}
}); //do other thing...
System.out.println("do other thing...");
} private static <T> Future<T> invoke(Callable<T> callable) {
AtomicReference<T> result = new AtomicReference<>();
AtomicBoolean finished = new AtomicBoolean(false); Future<T> future = new Future<T>() {
private Completable<T> completable; @Override
public T get() {
return result.get();
} @Override
public boolean isDone() {
return finished.get();
} @Override
public void setCompletable(Completable<T> completable) {
this.completable = completable;
} @Override
public Completable<T> getCompletable() {
return completable;
}
}; Thread t = new Thread(() -> {
try {
T value = callable.action();
result.set(value);
finished.set(true);
if (future.getCompletable() != null) {
future.getCompletable().complete(value);
}
} catch (Throwable cause) {
if (future.getCompletable() != null) {
future.getCompletable().exception(cause);
}
}
});
t.start(); return future;
} private interface Future<T> {
T get(); boolean isDone(); void setCompletable(Completable<T> completable); Completable<T> getCompletable();
} private interface Completable<T> {
void complete(T t); void exception(Throwable cause);
} private interface Callable<T> {
T action();
}
}

console打印:

do other thing...
complete. value = I am finished.  

----

CompletableFuture引入的更多相关文章

  1. JAVA8给我带了什么——Optional和CompletableFuture

    不管是JAVA,还是.NET.我们常常会看到空异常(NullPointerException).这种异常都是在运行的过程中出现.往往是变量是一个null值.但是你引用这个变量的后继字段或是方法.所以我 ...

  2. Future、 CompletableFuture、ThreadPoolTaskExecutor简单实践

    一 Future(jdk5引入) 简介: Future接口是Java多线程Future模式的实现,可以来进行异步计算. 可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算 ...

  3. 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】

    四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...

  4. CompletableFuture

    若你的意图是并发,而非并行,或者你的主要目标是在同一个CPU上执行几个松耦合的任务,充分利用CPU的核,让其足够忙碌,从而最大化程序的吞吐量,那么其实真正想做的避免因为等待远程服务的返回,或对数据库的 ...

  5. CompletableFuture 专题

    /** * @Auther: cheng.tang * @Date: 2019/3/2 * @Description: */ package com.tangcheng.learning.concur ...

  6. Java 8 (10) CompletableFuture:组合式异步编程

    随着多核处理器的出现,提升应用程序的处理速度最有效的方式就是可以编写出发挥多核能力的软件,我们已经可以通过切分大型的任务,让每个子任务并行运行,使用线程的方式,分支/合并框架(java 7) 和并行流 ...

  7. 有了 CompletableFuture,使得异步编程没有那么难了!

    本文导读: 业务需求场景介绍 技术设计方案思考 Future 设计模式实战 CompletableFuture 模式实战 CompletableFuture 生产建议 CompletableFutur ...

  8. Java8系列 (七) CompletableFuture异步编程

    概述 Java8之前用 Future 处理异步请求, 当你需要获取任务结果时, 通常的做法是调用  get(long timeout, TimeUnit unit) 此方法会阻塞当前的线程, 如果任务 ...

  9. Java8新特性--CompletableFuture

    并发与并行 Java 5并发库主要关注于异步任务的处理,它采用了这样一种模式,producer线程创建任务并且利用阻塞队列将其传递给任务的consumer.这种模型在Java 7和8中进一步发展,并且 ...

随机推荐

  1. composer问题集锦

    问题一:composer遇到Your configuration does not allow connection to 解决方案: 设置一个本地或全局的composer配置: composer c ...

  2. java8学习之Stream实例剖析

    继续操练Stream,直接上代码: 而咱们要返回ArrayList,显示可以用构造引用来传递到里面,因为它刚好符合Supplier函数式接口的特性:不接收参数返回一个值,所以: 接下来试着将Strea ...

  3. Gym - 102040F Path Intersection (树链剖分+线段树)

    题意:给出棵树上的k条路径,求这些路径的公共点数量. 将每条路径上的点都打上标记,被标记过k次的点就是公共点了.由于公共点形成的区间是连续的,因此直接在线段树上暴搜即可在$O(logn)$求出一条链上 ...

  4. HDU - 6253 Knightmare (打表+拉格朗日插值)

    题目链接 题意:一个马在无限大的棋盘中跳,问跳n步能跳到多少个不同的格子. 首先写个打表程序打一下n比较小的时候的表: #include<bits/stdc++.h> using name ...

  5. 最近老是有兄弟问我,Vue双向绑定的原理,以及简单的原生js写出来实现,我就来一个最简单的双向绑定,原生十行代码让你看懂原理

    废话不多说直接看效果图 代码很好理解,但是在看代码之前需要知道Vue双向绑定的原理其实就是基于Object.defineProperty 实现的双向绑定 官方传送门 这里我们用官方的话来说Object ...

  6. php的流程控制 if elseif swich case for循环

    if ......else 最简形式: <?php                              if (true){ echo "晚上找昌仔训练去";}?> ...

  7. java文件断点续传上传下载解决方案

    这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...

  8. 论文阅读:ClickNF: a Modular Stack for Custom Network Functions

    摘要: 网络功能虚拟化最近允许用等效的软件实现代替专用设备, Click路由器是朝这个方向迈出的第一步,它定义了用于通用数据包处理的模块化平台. 尽管Click具有重大影响,但它不提供本机L4实现,而 ...

  9. 游戏2048的python实现

    前些日子被问了一下2048是如何实现,说实话当时没有想的特别清晰,所以回答的也比较混乱,后来仔细想想这个问题还是挺有趣的,简单的实现了一下 这个问题里面主要有两个问题,一个是移动时的计算,二是移动前对 ...

  10. 我不熟悉的string类

    我不常用的string函数 多的不说,直接上: assign函数 string& assign(const char *s); //把字符串s赋给当前的字符串 string& assi ...