一、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. 2019-2020-1 20199319《Linux内核原理与分析》第四周作业

    MenuOS的构造 基础知识 1.操作系统的两把宝剑:①中断上下文的切换:保存现场和恢复现场:②进程上下文的切换. 2.Linux内核以A.B.C.D方式命名:A和B变得无关紧要,C是内核的真实版本, ...

  2. VMware三种网络模式详解

    转载自https://www.cnblogs.com/linjiaxin/p/6476480.html 好文章怕原始地址会不能用,转载到自己这里,感谢原作者的无私奉献. 由于Linux目前很热门,越来 ...

  3. 修改mysql的binlog的位置

    最近项目上装的mysql服务,分配的磁盘空间太小了,导致binlog两天时间就能打满,这里记录下处理方式 mysql的binlog日志是一个很重要的日志,以事件形式记录了所有的DDL和DML(除了数据 ...

  4. linux主机之间的SSH链接

    一.什么是SSH连接 SSH为Secyre Shell的缩写,SSH 为建立在应用层基础上的安全协议.SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议.且SSH连接可以通过多种平台 ...

  5. Ubuntu中出现“Could not get lock /var/lib/dpkg/lock”的解决方法

    在运行Ubuntu安装软件,使用命令sudo  apt-get install时,有时会出现以下的错误: E: Could not get lock /var/lib/dpkg/lock - open ...

  6. shell 获取结果中的第n列,第n行

    ls -l | awk '{print $5}' | sed -n '2p' awk 是很实用的文本处理命令,print 到后带的是你要获取第几列,sed -n 是指定第几行.

  7. Euler-path

    对于每个连通块欧拉回路存在的条件 无向图:只存在两个或者零个度数为奇数的点 有向图:每个点的入度等于出度或者至多有两个点入度不等于出度且一个出度比入度多一另一个入度比出度多一 HDU 多校第二场 C. ...

  8. Linux如何将pycharm添加到桌面

    使用Ubuntu编辑器,在/usr/share/applications 目录下创建一个 Pycharm.destop的文件. sudo vim /usr/share/applications/Pyc ...

  9. Spring boot使用Redis时,报错,有redisTemplate和stringRedisTemplate两个bean?

    Error starting ApplicationContext. To display the auto-configuration report re-run your application ...

  10. 多线程(二)Object类方法、线程的操作sleep(),join(),interrupt(),yield()

    四.Object类简介 Object类是所有类的超类,之所以放在线程部分是因为其方法很多是和线程有关的.比如以下三个: wait()方法.wait(long timeout)和wait(long ti ...