[置顶] JDK-Future 模式和实现
最近的项目用到了多线程,发现java.util.concurrent.Future蛮好用的。
像平时,写多线程一般使用Thread/Runnable,直接扔给线程池执行就好了。但是遇到了一些需要获取线程执行结果的情况,就需要使用Callable。对于使用Callable的task,ExecutorService执行后会返回一个Future对象来传递执行结果。
那这个Future是怎么存放返回值的呢,这个Future有什么值得使用的地方呢。我查了一下,发现原来还专门有个Future模式。
Future模式
Future模式在请求发生时,会先产生一个Future凭证给发出请求的客户,它的作用就像是Proxy物件,同时,由一个新的执行线程持续进行目标物件的生成(Thread-Per-Message),真正的目标物件生成之后,将之设定至Future之中,而当客户端真正需要目标物件时,目标物件也已经准备好,可以让客户提取使用。
结合JDK的Future来看,就是你run线程后,你可以把线程的返回值赋给Future并返回一个Future对象。这时你可以立即拿到这个对象,然后进行下面的逻辑。但是如果你要get这个Future中的线程结果,就会被阻塞直到线程结束。
就相当于现在的期房,你把手续和钱都交上去了,就可以马上拿到合同,但只有合同没有房子。这个时候你已经是有房一族了,你可以先去买家电买装修(走下面的其他逻辑)。但是你要把家电和装修放进去,就必须等到房子完工(阻塞)。
这样有一个好处,就是你把处理任务交给线程并拿到那个future凭证,就可以去干别的事情了(同时线程也在处理),等你真正要用到这个线程返回值的时候再通过future来获取,这样能缩短阻塞的时间。
Demo
接下来,我们看看Future的一个demo,这个例子很简单,就是为表明线程提交处理后,future对象是立即返回的,紧接着“Ready”马上就打印“Give the future”了;而当调用future.get的时候就停下了,“Get the future”迟迟没有打印,被阻塞了,直到线程执行完毕为止。这里我让他睡了3秒钟,能看得更清楚。
public class FutureTest {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
System.out.println("Ready");
Future strFuture = executor.submit(new TaskTest());
System.out.println("Give the future");
System.out.println("Get the future : " + strFuture.get());
System.out.println("End");
executor.shutdown();
}
public static class TaskTest implements Callable {
@Override
public String call() throws Exception {
Thread.sleep(3000);
return "Hello World!";
}
}
}
Simulator
从future的应用能看出来,其实future实现的功能很简单,就是充当一个线程返回结果的寄存器,只是在获取结果的时候,检查线程是否已完成,还在处理则阻塞,否则返回结果。
下面我做了一个future的模拟实现:
首先future作为一个结果寄存器,就需要有个result来存放结果,另外需要一个isFinish来标记线程是否完成。当然我在set()的时候不仅给result赋值,还把isFinish标记成完成,因为一般返回值都在线程结束时赋值的,所以我也这么简化设计了。
测试使用上面的demo,运行结果也是一样的。只是我的这个future没有JDK那个优雅和健壮,那个还整合到ExecutorService,用起来更方便。
【
所以,还有请大神们指导,这样的future实现,是不是还有什么漏洞?
】
public class FutureSimulator {
private volatile T result;
private volatile boolean isFinish = false;
public void set(T result) {
this.result = result;
this.isFinish = true;
}
public T get() throws InterruptedException {
while (!isFinish) {
Thread.sleep(100);
}
return result;
}
public static void main(String[] args) throws Exception {
FutureSimulator future = new FutureSimulator();
ExecutorService executor = Executors.newCachedThreadPool();
System.out.println("Ready");
executor.submit(new FutureTaskTest(future));
System.out.println("Give the future");
System.out.println("Get the future : " + future.get());
System.out.println("End");
executor.shutdown();
}
}
class FutureTaskTest extends Thread {
private FutureSimulator future;
public FutureTaskTest(FutureSimulator future) {
this.future = future;
}
@Override
public void run(){
try {
Thread.sleep(3000);
future.set("Hello World!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
[置顶] JDK-Future 模式和实现的更多相关文章
- [置顶] JDK工具(零)--简要介绍JDK1.6自带的42个工具
Java的开发人员肯定都知道JDK的bin目录中有“java.exe”和“javac.exe”这两个命令行工具, 但并非所有的Java程序员都了解过JDK的bin目录之中其它命令行程序的作用. JDK ...
- [置顶] lvs-tun隧道模式搭建
一.lvs直接路由原理 由于图片还要一张一张上传,可以到下面网站下载我的word版本: http://download.csdn.net/user/y0908105023 补充基础知识: OSI(Op ...
- [置顶] 单键模式的C++描述
设计模式-单键(Signelton):其实单键的设计模式说来很简单,说的直白一点就是程序运行过程中保证只有一个实例在运行而已.在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例, ...
- [置顶] 使用严苛模式打破Android4.0以上平台应用中UI主线程的“独断专行”
传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 已经有好一段时间没有关注Android应用方面的事情了:)最近单位来了一个Androi ...
- [置顶] JDK工具(一)–Java编译器javac
1.概述 javac.exe: Java编译器,将Java源代码转换成字节码. 2.用法 javac <选项> <源文件> (使用过程中发现,javac <源 ...
- Future模式的学习以及JDK内置Future模式的源码分析
并发程序设计之Future模式 一).使用Future模式的原因 当某一段程序提交了一个请求,期待得到一个答复,但服务程序对这个请求的处理可能很慢,在单线程的环境中,调用函数是同步的,必须等到服务程序 ...
- 【并发编程】Future模式及JDK中的实现
1.1.Future模式是什么 先简单举个例子介绍,当我们平时写一个函数,函数里的语句一行行同步执行,如果某一行执行很慢,程序就必须等待,直到执行结束才返回结果:但有时我们可能并不急着需要其中某行的执 ...
- Future模式
Future模式简介 Future模式有点类似于网上购物,在你购买商品,订单生效之后,你可以去做自己的事情,等待商家通过快递给你送货上门.Future模式就是,当某一程序提交请求,期望得到一个答复.但 ...
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
随机推荐
- js基础参数获取
1 获取浏览器中url中的参数,会自动把问号"?"去掉 function getParamsFromHref() { //调试用 var wyl_ = window.locatio ...
- git代码提交流程
1.进入我的项目文件夹所在目录: 2.git status 查看我修改过的文件: 3.git add -A 将修改的文件全部添加, git add 文件名 只添加指定的文件名: 4.git comm ...
- nyoj 21三个水杯(BFS + 栈)
题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=21 思想: 看了一下搜索就来写了这题(BFS 找出最短路径 所以用此来进行搜索) 这题在 ...
- JAVA和.NET互调用
通过接口实现JAVA和.NET互调用-JNInterface 使用C#编程多年,也十分感激微软在语言架构.语法糖.编辑器等方面给自己带来的便利.但因为最近工作中有接触到JAVA,渐渐地发现的确像大家说 ...
- LBA(逻辑区块地址)及PBA(物理区块地址)
LBA,全称为Logical Block Address,是PC数据存储装置上用来表示数据所在位置的通用机制,我们最常见到使用它的装置就是硬盘.LBA可以指某个数据区块的地址或者某个地址上所指向的数据 ...
- 浅谈 android-query
介绍:android-query他是在GitHub上的一个开源轻量级的封装库,它集成了网络 .图片加载等模块,可以应用在android中的一些异步应用以及UI的操纵上,通过使用这个框架,使androi ...
- API各函数作用简介
API各函数作用简介 1.控件与消息函数 AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小 AnyPopup 判断屏幕上是否存在任何弹出式窗口 ArrangeI ...
- linux线程之pthread_join和pthread_detach
在任何一个时间点上,线程是可结合的(joinable)或者是分离的(detached).一个可结合的线程能够被其他线程收回其资源和杀死.在 被其他线程回收之前,它的存储器资源(例如栈)是不释放的.相反 ...
- css3选择器的比较(三) -- 元素选择器 (+, ~)
元素选择器中w3cschool中有些翻译不太准确 比如 +:其实是与element1元素同级,位于element1元素之后的第一个element2元素 ~:其实是与element1元素同级,位于ele ...
- IDEA 15 社区版 Maven项目 启动Tomcat调试
1.在pom下添加Tomcat插件: <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifac ...