一、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. 外网访问VMware(Centos7.0,NAT模式)搭建的web服务器应用

    首先参考         https://www.cnblogs.com/studyhard-cq/p/11551755.html 设置好NAT模式,能访问公网. 1.打开VMware,点击左上角编辑 ...

  2. Linux 文件恢复(XFS & EXT4)

    在Linux中,删除rm命令使用需谨慎,有时候可能由于误操作,导致重要文件删除了,这时不要太紧张,操作得当的话,还是可以恢复的. EXT 类型文件恢复 删除一个文件,实际上并不清除inode节点和bl ...

  3. zabbix 邮件报警事件:Zabbix discoverer processes more than 75% busy

    Problem has been resolved at :: on Problem name: Zabbix discoverer processes more than % busy Host: ...

  4. Linux系统服务器 GNU Bash 环境变量远程命令执行漏洞修复命令

    具体方法就是在ssh上执行 yum update bash 完成后重启VPS.

  5. 程序中的一些限制(基于Linux系统C语言)

    今天突然想起来几个问题,在程序运行起来时,存在一些限制: 1,数组的长度(成员的个数)存在限制!(数组定义的空间大小)2,一个进程里打开的文件数.3,一个文件的名字的长度.4,一个进程里创建线程的个数 ...

  6. maven项目编译报错:Type Dynamic Web Module 3.0 requires Java 1.6 or newer.

    在maven的pom.xml文件中增加: <build>   <plugins>     <plugin>         <groupId>org.a ...

  7. list实现栈以及队列操作

    1.堆栈stack操作:尾进 尾出 或者叫先进后出 //1借助LinkedList 类中的方法实现栈 public class MyStack { private LinkedList<Obje ...

  8. selenium Error

    点击下载对应版本的 chromedriver.exe Message: 'geckodriver' executable needs to be in PATH. 原因是没有配置chromedrive ...

  9. 创建本地repo源

    1,保留rpm包 yum 安装时保留包至指定目录 编辑/etc/yum.conf 将keepcache的值设置为1: 2,使用插件 1,yum-plugin-downloadonly插件 sudo y ...

  10. [深度学习] 各种下载深度学习数据集方法(In python)

    一.使用urllib下载cifar-10数据集,并读取再存为图片(TensorFlow v1.14.0) # -*- coding:utf-8 -*- __author__ = 'Leo.Z' imp ...