Java多线程编程中Future模式的详解
转载自 https://www.cnblogs.com/winkey4986/p/6203225.html
Java多线程编程中,常用的多线程设计模式包括:Future模式、Master-Worker模式、Guarded Suspeionsion模式、不变模式和生产者-消费者模式等。这篇文章主要讲述Future模式,关于其他多线程设计模式的地址如下:
关于其他多线程设计模式的地址如下:
关于Master-Worker模式的详解: Java多线程编程中Master-Worker模式的详解
关于Guarded Suspeionsion模式的详解: Java多线程编程中Guarded Suspeionsion模式的详解
关于不变模式的详解: Java多线程编程中不变模式的详解
关于生产者-消费者模式的详解:生产者-消费者模式Java详解
1. Future模式核心思想
Future模式的核心在于:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑(根据《Java程序性能优化》)。
Future模式有点类似于商品订单。在网上购物时,提交订单后,在收货的这段时间里无需一直在家里等候,可以先干别的事情。类推到程序设计中时, 当提交请求时,期望得到答复时,如果这个答复可能很慢。传统的时一直等待到这个答复收到时再去做别的事情,但如果利用Future设计模式就无需等待答复 的到来,在等待答复的过程中可以干其他事情。
例如如下的请求调用过程时序图。当call请求发出时,需要很长的时间才能返回。左边的图需要一直等待,等返回数据后才能继续其他操作;而右边的 Future模式的图中客户端则无需等到可以做其他的事情。服务器段接收到请求后立即返回结果给客户端,这个结果并不是真实的结果(是虚拟的结果),也就 是先获得一个假数据,然后执行其他操作。
2. Future模式Java实现
Client的实现
Client主要完成的功能包括:1. 返回一个FutureData;2.开启一个线程用于构造RealData。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class Client {
public Data request( final String string) {
final FutureData futureData = new FutureData();
new Thread( new Runnable() {
@Override
public void run() {
//RealData的构建很慢,所以放在单独的线程中运行
RealData realData = new RealData(string);
futureData.setRealData(realData);
}
}).start();
return futureData; //先直接返回FutureData
}
}
|
Data的实现
无论是FutureData还是RealData都实现该接口。
1
2
3
|
public interface Data {
String getResult() throws InterruptedException;
}
|
FutureData的实现
FutureData是Future模式的关键,它实际上是真实数据RealData的代理,封装了获取RealData的等待过程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//FutureData是Future模式的关键,它实际上是真实数据RealData的代理,封装了获取RealData的等待过程
public class FutureData implements Data {
RealData realData = null ; //FutureData是RealData的封装
boolean isReady = false ; //是否已经准备好
public synchronized void setRealData(RealData realData) {
if (isReady)
return ;
this .realData = realData;
isReady = true ;
notifyAll(); //RealData已经被注入到FutureData中了,通知getResult()方法
}
@Override
public synchronized String getResult() throws InterruptedException {
if (!isReady) {
wait(); //一直等到RealData注入到FutureData中
}
return realData.getResult();
}
}
|
RealData的实现
RealData是最终需要使用的数据,它的构造函数很慢。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class RealData implements Data {
protected String data;
public RealData(String data) {
//利用sleep方法来表示RealData构造过程是非常缓慢的
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
this .data = data;
}
@Override
public String getResult() {
return data;
}
}
|
测试运行
主函数主要负责调用Client发起请求,并使用返回的数据。
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Application {
public static void main(String[] args) throws InterruptedException {
Client client = new Client();
//这里会立即返回,因为获取的是FutureData,而非RealData
Data data = client.request( "name" );
//这里可以用一个sleep代替对其他业务逻辑的处理
//在处理这些业务逻辑过程中,RealData也正在创建,从而充分了利用等待时间
Thread.sleep( 2000 );
//使用真实数据
System.out.println( "数据=" +data.getResult());
}
}
|
3. Future模式的JDK内置实现
由于Future是非常常用的多线程设计模式,因此在JDK中内置了Future模式的实现。这些类在java.util.concurrent包 里面。其中最为重要的是FutureTask类,它实现了Runnable接口,作为单独的线程运行。在其run()方法中,通过Sync内部类调用 Callable接口,并维护Callable接口的返回对象。当使用FutureTask.get()方法时,将返回Callable接口的返回对象。 同样,针对上述的实例,如果使用JDK自带的实现,则需要作如下调整。
首先,Data接口和FutureData就不需要了,JDK帮我们实现了。
其次,RealData改为这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import java.util.concurrent.Callable;
public class RealData implements Callable {
protected String data;
public RealData(String data) {
this .data = data;
}
@Override
public String call() throws Exception {
//利用sleep方法来表示真是业务是非常缓慢的
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
return data;
}
}
|
最后,在测试运行时,这样调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class Application {
public static void main(String[] args) throws Exception {
FutureTask futureTask =
new FutureTask( new RealData( "name" ));
ExecutorService executor =
Executors.newFixedThreadPool( 1 ); //使用线程池
//执行FutureTask,相当于上例中的client.request("name")发送请求
executor.submit(futureTask);
//这里可以用一个sleep代替对其他业务逻辑的处理
//在处理这些业务逻辑过程中,RealData也正在创建,从而充分了利用等待时间
Thread.sleep( 2000 );
//使用真实数据
//如果call()没有执行完成依然会等待
System.out.println( "数据=" + futureTask.get());
}
}
|
本文完。转载请注明出处。
参考文献
葛一鸣,Java程序性能优化.清华大学出版社.
转自 http://www.2cto.com/kf/201411/351903.html
Java多线程编程中Future模式的详解相关推荐
- 详解Java多线程编程中LockSupport类的线程阻塞用法
转载自 详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...
- Java多线程实现跑步比赛【比赛详解】
文章目录 文章链接 实现要求 比赛详解 文章链接 Java多线程实现跑步比赛[比赛详解] Java多线程实现跑步比赛[基本设计] Java多线程实现跑步比赛[RunMap--地图映射类] Java多线 ...
- java 多线程同步_详解Java多线程编程中的线程同步方法
1.多线程的同步: 1.1.同步机制:在多线程中,可能有多个线程试图访问一个有限的资源,必须预防这种情况的发生.所以引入了同步机制:在线程使用一个资源时为其加锁,这样其他的线程便不能访问那个资源了,直 ...
- java多线程的6种实现方式详解
多线程的形式上实现方式主要有两种,一种是继承Thread类,一种是实现Runnable接口.本质上实现方式都是来实现线程任务,然后启动线程执行线程任务(这里的线程任务实际上就是run方法).这里所说的 ...
- java调用项目中的文件_详解eclipse项目中.classpath文件的使用
1 前言 在使用eclipse或者myeclipse进行java项目开发的时候,每个project(工程)下面都会有一个.classpath文件,那么这个文件究竟有什么作用? 2 作用 .classp ...
- java的vector_Java中 Vector的使用详解
Vector 可实现自动增长的对象数组. java.util.vector提供了向量类(Vector)以实现类似动态数组的功能. 创建了一个向量类的对象后,可以往其中随意插入不同类的对象,即不需顾及类 ...
- Python面向对象编程(类编程)中self的含义详解(简单明了直击本质的解释)
以下是博主认为的对self讲解得比较透彻又简洁明了的资料. 上面的资料把这个问题说得简单明了,大家认真看一遍相信就对self有个深入的了解了. 总结一下: 在Python为面向对象编程中,成员函数被调 ...
- Java去除字符串中空格的方法详解
昨天写了一个关于Excel文件处理的脚本,在字符串匹配功能上总是出现多余不正确的匹配,debug调试之后,发现一个坑. 代码中字符串使用了replaceAll()方法,去除了所有空格(其中包括:首尾空 ...
- java中的locksupport_详解Java多线程编程中LockSupport
LockSupport是用来创建锁和其他同步类的基本线程阻塞原语. LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark() ...
最新文章
- [实用]DNS解析命令,静静地学会【转载】
- 炫“库”行动-人大金仓征文大赛—数据领域“新·独角兽”
- 如何定制化SAP Spartacus的购物车图标
- apache hadoop_使用Apache Hadoop计算PageRanks
- DNS服务器 安装部署 以及子域授权和转发
- es6 Atomics对象
- 重新实现unity3d的Mecanim动画混合 (2) 2D Freeform Cartesian
- Netty的并发编程实践2:volatile的正确使用
- ofd 文件发票解析
- 想多赚钱!程序员如何把副业搞得风生水起?
- RTT移植STM32之创建进程
- PLC浏览器端机械动画仿真(nodejs、vue)
- 对话思贤科技CEO姜华:深耕政务金融,思贤科技做行业赋能者
- 【听课笔记】复旦大学遗传学_10肿瘤遗传学
- 2022学生党蓝牙耳机怎么选?最新蓝牙耳机排行榜
- 一周小结(七)——从零开始配置VINS-Mono运行环境
- ubuntu16.04对比工具Meld安装和使用
- 鸿蒙基于linux系统,鸿蒙操作系统(HarmonyOS)是基于Linux的吗?尽管已知道它是基于微内核的...
- ed2k 网络中搜索资源并选择资源下载的分析及eMule源码梳理
- 苹果手机中病毒显示无服务器,苹果手机中毒五大特征!一般认为这是正常现象,你的iPhone中了吗...
热门文章
- _variant_t和_bstr_t有什么区别
- 如何阅读《深入理解计算机系统》?(文末送书)
- 面试题:1 到 1000 之间有多少个 7?
- 一个字符串中到底能有多少个字符? 我竟然算错了!
- 数据结构--图(Graph)详解(四)
- 【专场报名】七牛云音画质量优化专场
- 网易云信自研大规模传输网核心系统架构剖析
- 理查德·汉明和他的汉明码
- IBM Cloud:裸金属服务器+多云策略助力音视频解决方案成功出海
- 争做RTC领域标杆——与华为云副总裁薛浩聊聊我们的视频时代