CompletableFuture引入
一、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引入的更多相关文章
- JAVA8给我带了什么——Optional和CompletableFuture
不管是JAVA,还是.NET.我们常常会看到空异常(NullPointerException).这种异常都是在运行的过程中出现.往往是变量是一个null值.但是你引用这个变量的后继字段或是方法.所以我 ...
- Future、 CompletableFuture、ThreadPoolTaskExecutor简单实践
一 Future(jdk5引入) 简介: Future接口是Java多线程Future模式的实现,可以来进行异步计算. 可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算 ...
- 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】
四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...
- CompletableFuture
若你的意图是并发,而非并行,或者你的主要目标是在同一个CPU上执行几个松耦合的任务,充分利用CPU的核,让其足够忙碌,从而最大化程序的吞吐量,那么其实真正想做的避免因为等待远程服务的返回,或对数据库的 ...
- CompletableFuture 专题
/** * @Auther: cheng.tang * @Date: 2019/3/2 * @Description: */ package com.tangcheng.learning.concur ...
- Java 8 (10) CompletableFuture:组合式异步编程
随着多核处理器的出现,提升应用程序的处理速度最有效的方式就是可以编写出发挥多核能力的软件,我们已经可以通过切分大型的任务,让每个子任务并行运行,使用线程的方式,分支/合并框架(java 7) 和并行流 ...
- 有了 CompletableFuture,使得异步编程没有那么难了!
本文导读: 业务需求场景介绍 技术设计方案思考 Future 设计模式实战 CompletableFuture 模式实战 CompletableFuture 生产建议 CompletableFutur ...
- Java8系列 (七) CompletableFuture异步编程
概述 Java8之前用 Future 处理异步请求, 当你需要获取任务结果时, 通常的做法是调用 get(long timeout, TimeUnit unit) 此方法会阻塞当前的线程, 如果任务 ...
- Java8新特性--CompletableFuture
并发与并行 Java 5并发库主要关注于异步任务的处理,它采用了这样一种模式,producer线程创建任务并且利用阻塞队列将其传递给任务的consumer.这种模型在Java 7和8中进一步发展,并且 ...
随机推荐
- Ansible安装部署和常用命令,及其主机清单inventory(二)
1.ansible的安装方式 1.1使用yum源安装 yum install ansible -y 1.2使用rpm包安装 https://dl.fedoraproject.org/pub/epel/ ...
- linux系统使用grep命令提取文件的基名或者路径名
效果等于~]#dirname /etc/sysconfig/network-scripts/ifcfg-ens33 echo "/etc/sysconfig/network-scripts/ ...
- 如何在 Ubuntu 上安装 pip
1.为 Python 2 安装 pip 首先,确保已经安装了 Python 2. 在 Ubuntu 上,可以使用以下命令进行验证 python2 --version 如果没有错误并且显示了 Pytho ...
- ES数据架构与关系数据库Mysql
ES数据架构的主要概念(与关系数据库Mysql对比) MySQL ElasticSearch Database Index Table Type Row Document Column Field S ...
- js实现计时 时分秒
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [uboot] (第三章)uboot流程——uboot-spl代码流程 后续2018版本分析
board_init_f在/u-boot-2018.07-fmxx/arch/arm/mach-fmxx/spl.c中定义 board_init_f之后,和转载的部分有出入: u-boot-2018. ...
- Rest_Framework简介
Web应用模式 在开发Web应用中,有两种应用模式:前后端不分离和前后端分离 前后端不分离 前后端不分离通俗来讲就是不区分前端和后端,浏览器请求时服务器直接返回页面,其示意图如下 前后端分离 前后端分 ...
- linux7buffer和cache
现象:作为hdfs集群的主节点,越来越卡 排查:CPU,mem CPU正常,检查内存情况,发现如下 如上截图:发现程序可用内存为91G,但是部分swap分区被占用.于是引出如下思考,free -h这条 ...
- PHP大文件上传断点续传源码
文件夹数据库处理逻辑 publicclass DbFolder { JSONObject root; public DbFolder() { this.root = new JSONObject(); ...
- 3.决策树ID3算法原理
1.决策树的作用 主要用于解决分类问题的一种算法 2.建立决策树的3中常用算法 1).ID3--->信息增益 2).c4.5--> 信息增益率 4).CART Gini系数 3.提出问题: ...