当前位置: 首页 > 编程日记 > 正文

[面试]future模式

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;}@Overridepublic int getResult() {return data;}
}

FutureData类

public class FutureData implements Data {// 真实数据RealData的引用.private RealData realData = null;public synchronized void setRealData(RealData realData) {// 如果this.realData不是空, 说明已经准备好了, 直接returnif (this.realData != null)return;this.realData = realData;notifyAll();}@Overridepublic 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就是FutureDataData 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;}@Overridepublic 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 dataFutureTask<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();}}
}

转载于:https://www.cnblogs.com/noKing/p/9244818.html

相关文章:

java ide

tidespringsource sts a vmware product plugin:Aptana Studio 3(集成了Git) Run on Jettyeclipse for jee plugin:JBoss Tools,m2eclipe,spirng tools,svn

成长秘笈:是你教我,不是我教你

郑昀 20180622 “谢谢你&#xff0c;你是第一个面试的时候跟我说这么详细的。那我到你们公司之后怎么就能成长了呢&#xff1f;” “你们这些人最大的问题是出不了方案。 为什么出不了方案&#xff1f; 因为没有养成深度思考问题的习惯。 实现方案、算法、数据迁移、准备数据、…

计算机网络面试题(一)

1、OSI&#xff0c;TCP/IP&#xff0c;五层协议的体系结构&#xff0c;以及各层协议 OSI分层 &#xff08;7层&#xff09;&#xff1a;物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 TCP/IP分层&#xff08;4层&#xff09;&#xff1a;网络接口 网络层、运…

Ubuntu下安装和配置Apache2

在Ubuntu中安装apache 安装指令&#xff1a;sudo apt-get install apache2 安装结束后&#xff1a; 产生的启动和停止文件是&#xff1a;/etc/init.d/apache2 启动&#xff1a;sudo apache2ctl -k start 停止&#xff1a;sudo apache2ctl -k stop 重新启动&#xff1a;sudo apa…

苹果电脑安装python3密码_mac系统安装Python3初体验

前沿 对于iOS开发不要随便拆卸系统自带的Python,因为有很多 library 还是使用 Python2.7。 1 安装Xcode 1.1 App Store 搜索Xcode 并安装 1.2 安装 Xcode command line tool 1.2.1 打开命令行terminal工具 control space 输入terminal 回车 1.2.2 安装Xcode command line tool…

【IBM Tivoli Identity Manager 学习文档】3 系统部署

作者&#xff1a;gnuhpc 出处&#xff1a;http://www.cnblogs.com/gnuhpc/ ITIM 5.0 单服务器配置和部署。 部署ITIM之前要对其组件进行部署&#xff1a; IBM DB2 Enterprise 9.1 with FP2 IBM WebSphere Application Server 6.1 with FP9 IBM Tivoli Directory Server 6.2 IB…

数据结构Java版之红黑树(八)

红黑树是一种自动平衡的二叉查找树&#xff0c;因为存在红黑规则&#xff0c;所以有效的防止了二叉树退化成了链表&#xff0c;且查找和删除的速度都很快&#xff0c;时间复杂度为log(n)。 什么是红黑规则&#xff1f; 1.根节点必须是黑色的。 2.节点颜色要么是红要么是黑。 3.…

你真的了解Grid布局吗?

Grid网格布局 概述&#xff1a;Grid将容器划分为一个个网格&#xff0c;通过任意组合不同的网格&#xff0c;做出你想想要的布局 Grid与flex布局相似&#xff0c;将整个Grid分为了容器与子项&#xff08;格子&#xff09; Grid容器的三个重要的概念&#xff1a; 行和列单元格网…

webform里的验证控件

1.非空验证控件&#xff1a;RequireFieldValidator &#xff1b;2.数据比较验证&#xff1a;CompareValidator &#xff1b;3.数据范围验证&#xff1a;RangeValidator &#xff1b;4.正则表达式验证&#xff1a;RegularExpressionValidator &#xff1b;5.自定义条件验证&…

hash是线程安全的吗?怎么解决?_这次进程、线程、多线程和线程安全问题,一次性帮你全解决了...

1. 什么是进程一个软件&#xff0c;在操作系统中运行时&#xff0c;我们称其为进程。进程是操作系统分配资源的最小单元&#xff0c;线程是操作系统调度的最小单元。2. 什么是线程在一个进程中&#xff0c;每个独立的功能都需要独立的去运行&#xff0c;这时又需要把当前这个进…

WinXP不能共享Win7的打印机的解决方法

现在很多企业里存在着WinXP和Win7混用&#xff0c;WinXP不能正常共享Win7的文件和打印机&#xff0c;经过设置发现Win7可以Ping通Winxp并且也可以发现WinXP的共享文件&#xff0c;可是WinXP却不能共享Win7的文件和打印机&#xff0c;看了一下相关资料后简单设置就解决了这个问题…

第三阶段 10_JavaWeb基础_

因为要准备接本&#xff0c;不一定能够每天更新 转载于:https://www.cnblogs.com/BaiZe258/p/9251075.html

工厂模式(Factory)(转)

先来明确一个问题&#xff0c;那就是有的时候&#xff0c;实例化这个活动不应该总是公开的进行&#xff0c; 也就是不要公开的使用 new 操作符&#xff0c;因为&#xff0c;这样容易造成耦合问题。 我们不应该针对实现编程&#xff0c;但是当我们在使用 new 的时候&#xff0c;…

Asp.net后台创建HTML

为了使HTML界面中的内容能根据数据库中的内容动态显示用户需要的内容&#xff0c;或者根据权限不同要显示同而实现页面内容的动态创建 使用HtmlGenericControl创建HTML标签 引入命名空间: using System.Web.UI.HtmlControls; 更改其属性: hgg_div.Attributes.Add("style&q…

oracle视图(转)

视图的概念 视图是基于一张表或多张表或另外一个视图的逻辑表。视图不同于表&#xff0c;视图本身不包含任何数据。表是实际独立存在的实体&#xff0c;是用于存储数据的基本结构。而视图只是一种定义&#xff0c;对应一个查询语句。视图的数据都来自于某些表&#xff0c;这些…

Redis 事物

redis 事物&#xff1a; Redis 事物的实现&#xff1a; 首先 wath监控键值 myKey开启批量执行 multi&#xff0c;执行命令入列&#xff0c;执行 exec 。如果监控的键值mykey 没有被修改过&#xff0c;则exec 中批量执行的命令成功&#xff0c;否则执行失败。无论执行成功与否&a…

python dos攻击_利用SMB漏洞DoS攻击任何Windows系统

原标题&#xff1a;利用SMB漏洞DoS攻击任何Windows系统近日微软报出SMB V1存在漏洞&#xff0c;安全研究员并将此漏洞称作 “ SMBLoris ”&#xff0c;解释其能够发动拒绝服务&#xff08;Dos&#xff09;攻击&#xff0c;可以感染 Windows 2000 及以上操作系统的任一版本 SMB …

java基础编程题(2)

1、给定一个二叉树&#xff0c;找出其最大深度。 注&#xff1a;二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x…

python元组转字典_python中怎么将元组、字典转化为列表

python中将元组、字典转化为列表的方法&#xff1a; python中可以使用list()方法将元组或字典转化为列表&#xff1a; list()方法语法&#xff1a;list( tup ) 参数 tup -- 要转换为列表的元组。 返回值 返回列表。 示例&#xff1a; 将元组转换为列表&#xff1a;#!/usr/bin/p…

搭建Git服务器教程转载

1. 在Windows下使用sshmsysgit客户端搭建Git服务器 http://www.codeproject.com/Articles/296398/Step-by-Step-Setup-Git-Server-on-Windows-with-CopS 2. 在Windows下使用Apachemsysgit客户端搭建Git服务器 http://www.devbean.info/2011/10/apache-git-server-on-windows/ 3…

存储过程处理错误数据

create or replace procedure ERR_REDUCEDATA is --sx --定义变量 v_realindiobjid VARCHAR2(100); v_indiobjid VARCHAR2(32); v_residuemoney number ; v_reducemoney number ; v_approbjid VARCHAR2(32); -- v_indiecoid VARCHAR2(32); --v_indiecocode VARCHAR2(32); v_Ap…

[置顶] 面向业务开发应用

自从计算机出现后&#xff0c;快速便捷的从太平洋一样的文海中找到水滴大小的资料真正成为了可能&#xff0c;而能够帮助人们实现这一愿望的程序员就像中世纪的航海家一样用神秘的代码程序指引着计算机一步一步实现的需求。而他们所用的被称之为“程序”的序列组合&#xff0c;…

vector方法

借鉴网上资料&#xff0c;整理了vector使用的一些方法&#xff0c;记录下来&#xff0c;方便以后查阅 vector初始化 vector<int>a(10) //只定义长度 vector<int>a(10,1)//长度为10&#xff0c;初始值为1 vector<int>a(b); //用b向量来创建a向量&#xff0c;…

MyEclipse Enterprise Workbench 9.0 破解及注册机 注册码

MyEclipse 9.0的激活机制终于破解了&#xff0c;破解步骤比老版本要复杂一些&#xff0c;但是是绝对可以破解的&#xff0c;这个破解对主程序无任何修改&#xff0c;只替换公钥&#xff0c;如果有牛人会快速从公钥反推私钥&#xff0c;那就什么都不用改了&#xff0c;步骤如下&…

python字典一键多值_python字典中如何一键多值的写入?

python字典中如何一键多值的写入&#xff1f; python字典中一键多值写入的方法&#xff1a; 1、循环写入字典key、value、删除指定的键值对&#xff1a; 原文本‘jp_url.txt’每行元素以逗号分隔:host_key,product_id,product_name,cont_start,cont_end ah2.zhangyue.com,10000…

向实现细节低头

本来想搞明白所有的东西&#xff0c;然后自己集成&#xff0c;避免引入额外的组件&#xff0c;避免复杂的维护成本。 现在想想&#xff0c;相比于投入的巨大精力&#xff0c;其收益过小&#xff0c;还是要有所取舍。转载于:https://www.cnblogs.com/youge-OneSQL/p/9268924.htm…

Session丢值的问题

本来本地调试好好的,一上服务器session就非常容易丢失,表现在,用window.href跳转丢session,用httpmoulde丢session,在frame里面ifarme里面丢session,折磨了一天,才知道是因为应用程序池的原因,一个池里面放了太多网站,导致session丢失(系统还没有上线,光放那也不行), 还有应用程…

换发型app任性扣费?苹果app订阅任性扣费?怎么办?刚成功

2019年9月18日17:09:27 什么黑猫举报没用 先关闭订阅 账户中心自助申请试试&#xff0c;不通过再进行下面这步 https://getsupport.apple.com/?callerhome&PRKEYS 技术支持网址 然后就等电话吧&#xff0c;一般10秒钟就打过来了。 告诉原因&#xff0c;提供收费的订单号&a…

用eclipse阅读编辑android和kernel,uboot的源代码

from: http://hi.baidu.com/designhouse/blog/item/ff3f0df4a33571f37709d736.html 1. 用eclipse阅读编辑android源代码的配置方法有官方文档&#xff0c;非常详细&#xff0c;http://source.android.com/source/using-eclipse.html 阅读android代码用的是Eclipse IDE for Jav…