Future模式

什么是future模式?

传统单线程环境下,调用函数是同步的,必须等待程序返回结果后,才可进行其他处理。 Futrue模式下,调用方式改为异步。

Futrue模式的核心在于:充分利用主函数中的等待时间,利用等待时间处理其他任务,充分利用计算机资源。

简单描述一下future模式的实现

future模式有两种数据, 一种是真实数据RealData, 里面就是业务中想要得到的目标数据. 另一种是虚拟数据FutureData, 它是在使用future模式时立即返回的一个对象.

调用方会首先拿到一个FutureData, 然后调用方就认为自己拿到该数据了, 没有进行阻塞, 继续去执行下面的逻辑处理. 如果真实数据准备好了, 就会把自己的引用赋给之前的那个FutureData, 并且置一个标记, 表示这个FutureData里面包含一个RealData, 拿到了想要的数据, 可以使用.

详细分的话, 会有下面这几种情况(假设RealData需要2秒才能创建好):

1. 调用方发送了自己需要RealData的请求的后, 会立即拿到一个FutureData, 但是根本就不着急使用, 所以, 第2秒的时候RealData创建完成后, 就会被绑定到对应的FutureData里. 假设第6秒调用方才开始使用RealData, 他会发现FutureData已经准保好了他想要的数据, 于是开心地使用就ok了.

2. 调用方发送了自己需要RealData的请求的后, 会立即拿到一个FutureData, 但是很着急使用, 因为接下来的处理过程依赖于RealData的内容. 于是在第0.5秒的时候, 调用方就想要获取RealData. 但是这个时候RealData并没有准备好, 此时的FutureData是一个空壳而已. 所以就在这里进行wait(或者忙等待). 直到RealData准备好,也就是再过1.5秒, 线程才会唤醒(或者打破忙等待).

请用代码实现一下Future模式

FutureData和RealData的统一抽象接口, Data类如下:

public interface Data {
int getResult() throws InterruptedException;
}

RealData类

public class RealData implements Data {
private int data; public RealData(int num) {
//这里用sleep来模拟构造一个复杂对象的场景
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} this.data = num * 10;
} @Override
public int getResult() {
return data;
}
}

FutureData类

public class FutureData implements Data {
// 真实数据RealData的引用.
private RealData realData = null; public synchronized void setRealData(RealData realData) {
// 如果this.realData不是空, 说明已经准备好了, 直接return
if (this.realData != null)
return;
this.realData = realData;
notifyAll();
} @Override
public synchronized int getResult() throws InterruptedException {
// 如果this.realData是null, 说明数据还没准备好, 应该等待
if (this.realData == null) {
wait();
}
return realData.getResult();
}
}

Client类

直接创建一个FutureData, 然后直接返回这个FutureData. 同事开辟一个线程来创建RealData, 并且在RealData创建完后绑定在FutureData中.

public class Client {
public Data request(final int num) {
// 当有请求的时候, 先创建一个虚拟对象.
final FutureData futureData = new FutureData(); // 然后开启一个新线程去创建RealData, 当RealData创建完成后, 绑定带FutureData里.
new Thread(() -> {
RealData realData = new RealData(num);
futureData.setRealData(realData);
}).start(); // 不管RealData有没有创建完成, 都会直接返回这个FutureData.
return futureData;
}
}

Main

调用这个Future模型.

public class Main {
public static void main(String[] args) throws InterruptedException {
Client client = new Client(); // 调用了之后会立即返回一个FutureData, 这个data就是FutureData
Data data = client.request(4); // 用sleep来模拟主线程正在处理其他事情
Thread.sleep(0); // getResult来获取真实数据
// |- 如果这时候真实数据没准备好, 那么就wait, 等待notify, 然后获取到真实数据
// |- 如果这时候真实数据准备好了, 那么就可以直接获取到了
System.out.println("数据=" + data.getResult());
}
}

在RealData处进行了*10 的处理, 所以request(4), 最终会返回40.

使用过JDK自带的Future模式吗?

使用过, 例子如下:

定义一个RealData类

import java.util.concurrent.Callable;

public class RealData implements Callable<Integer> {
private int data; public RealData(int data) {
this.data = data * 10;
} @Override
public Integer call() {
//利用sleep方法来表示真是业务是非常缓慢的
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return data;
}
}

Main

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask; public class Main {
public static void main(String[] args) throws Exception {
//线程池
ExecutorService executor = Executors.newFixedThreadPool(1); //使用线程池 // 之前自己实现的future模式中的 Data data = client.request(4) 这句相当于下面这两行代码
//1. Data data
FutureTask<Integer> futureTask = new FutureTask<>(new RealData(4));
//2. 这里相当于 client.request(4);
executor.submit(futureTask); //这里可以用一个sleep代替对其他业务逻辑的处理
Thread.sleep(0); // 获取真实数据
try {
System.out.println("数据=" + futureTask.get());
}finally {
executor.shutdown();
}
}
}

[面试]future模式的更多相关文章

  1. 13.多线程设计模式 - Future模式

    多线程设计模式 - Future模式 并发设计模式属于设计优化的一部分,它对于一些常用的多线程结构的总结和抽象.与串行相比并行程序结构通常较为复杂,因此合理的使用并行模式在多线程并发中更具有意义. 1 ...

  2. 线程笔记:Future模式

    线程技术可以让我们的程序同时做多件事情,线程的工作模式有很多,常见的一种模式就是处理网站的并发,今天我来说说线程另一种很常见的模式,这个模式和前端里的ajax类似:浏览器一个主线程执行javascri ...

  3. 架构师养成记--9.future模式讲解

    什么是future模式呢?解释这个概念之前我们先来了解一个场景吧,财务系统的结账功能,这个功能可能是每个月用一次,在这一个月中相关的数据量已经积累得非常大,这一个功能需要调用好几个存储过程来完成.假如 ...

  4. Future模式

    Future模式简介 Future模式有点类似于网上购物,在你购买商品,订单生效之后,你可以去做自己的事情,等待商家通过快递给你送货上门.Future模式就是,当某一程序提交请求,期望得到一个答复.但 ...

  5. 闲谈Future模式-订蛋糕

    一. Future模式简介 Future有道翻译:n. 未来:前途:期货:将来时.我觉得用期货来解释比较合适.举个实际生活中例子来说吧,今天我女朋友过生日,我去蛋糕店准备给女朋友定个大蛋糕,超级大的那 ...

  6. 线程技术 ☞ Future模式

    线程技术可以让我们的程序同时做多件事情,线程的工作模式有很多,常见的一种模式就是处理网站的并发,今天我来说说线程另一种很常见的模式,这个模式和前端里的ajax类似:浏览器一个主线程执行javascri ...

  7. java Future 模式

    考慮這樣一個情況,使用者可能快速翻頁瀏覽文件中,而圖片檔案很大,如此在瀏覽到有圖片的頁數時,就會導致圖片的載入,因而造成使用者瀏覽文件時會有停頓 的現象,所以我們希望在文件開啟之後,仍有一個背景作業持 ...

  8. Java多线程编程中Future模式的详解

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  9. 多线程之Future模式

    详细参见葛一名老师的<Java程序性能优化> Futrue模式:对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果 ...

随机推荐

  1. Jmeter输出完美报告

    做技术的就爱折腾, 看到哪里不够完美,就想把它改改, 使其顺眼. 同样Jmeter输出的报告实在差强人意, 截图发给领导看不够美观, 缺少统计汇总, 有什么方法给对方一个地址就可以浏览报告? 答案是肯 ...

  2. Docker-Dockerfile及基本语法

    Dockerfile的作用是通过它可以生成自定镜像,先介绍几个基本的docker命令. [docker镜像相关的命令]docker search 镜像名: 搜索镜像docker pull 镜像名: 镜 ...

  3. 微软与开源干货对比篇_PHP和 ASP.NET在 Session实现和管理机制上差异

    微软与开源干货对比篇_PHP和 ASP.NET在 Session实现和管理机制上差异 前言:由于开发人员要靠工具吃饭,可能和开发工具.语言.环境呆的时间比和老婆孩子亲人在一起的时间还多,所以每个人或多 ...

  4. Redis基础一(Linux)

    Redis概述 1.是一个开源的,先进的<key,value>存储,并用与构建高性能,可扩展的应用程序的完美解决方案 2.从它的许多竞争继承来的三个主要特点: l  Redis数据库完全在 ...

  5. java jdk动态代理(proxy)

    1. 涉及主要jdk api java.lang.reflect.InvocationHandler: public interface InvocationHandler { /** * Proce ...

  6. Docker容器镜像删除

    好吧,本来认为删除镜像是一件很容易的事情,但刚开始上手,还是有点百思不得其解.删着删着,发现果然很容易.分享下本人的心得: 分两种情况:那么要删除镜像,首先得删除容器,删除容器时,确保容器已停止运行: ...

  7. Linux:Day20(上) openssh和CA

    ssh:secure shell protocol,22/tcp,安全的远程登陆 OpenSSH:ssh协议的开源实现: dripbear:另一个开源实现: SSH协议版本 v1:基于CRC-32做M ...

  8. Mybatis中接口和对应的mapper文件命名为什么需要一样?

    背景: 自己对于Mybatis现阶段只处于会用的阶段,有些问题,自己还是想深入的了解一下.就拿Mybatis的接口文件和mapper文件命名需要一致来开始. 解决: 当我们将接口和mapper文件放在 ...

  9. 初识Haskell 四:函数function之二 常见函数

    对Discrete Mathematics Using a Computer的第一章Introduction to Haskell进行总结.环境Windows,关于函数的部分太长了,分开写. 常用的对 ...

  10. Go之运算符

    逻辑运算符用于连接布尔型表达式.在Java中不同于数学的逻辑表达 3<X<5 ,java 中应该写成 x>3 & x<5 "&" 和&quo ...