Future模式模拟
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Future模式模拟相关的知识,希望对你有一定的参考价值。
Future模式是一种非常常见的设计模式,其核心思想就是异步调用。
1. Future模式的主要参与者
参与者 | 作用 | 备注 |
---|---|---|
Main | 系统启动,调用client发出请求 | 可以看做是一个应用 |
client | 用于返回Data对象,立即返回FutureData,并开启一个线程装配RealData | |
Data | 返回数据的接口 | |
FutureData | FutureData实现了Data接口,构造很快,是一个虚拟数据,需要装配RealData真实数据 | 也可以看做是构造一个空的Data对象,按字面意思来看就是将来的数据,还没有...,当客户端需要使用数据时需要设置成RealData对象 |
RealData | 真实数据,起构造可能会比较慢,RealData也实现了Data接口 | 这个数据才是Main应用需要的 |
2. Future模式流程图如下:
3. Future模式的简单实现
3.1 核心接口Data
/**
* Created with IntelliJ IDEA.
* User:
* Date: 2018/12/29
* Time: 下午6:47
* Description: Data接口有两个重要的实现,FutureData和RealData,RealData代表的是真实数据,FutureData是真实数据的代理或者说是包装
*/
public interface Data {
String getResult();
}
/**
* Created with IntelliJ IDEA.
* User:
* Date: 2018/12/29
* Time: 下午6:44
* Description: 实现Data接口,其功能是对RealData进行包装、代理,在FutureClient请求Data数据时,将立即返回一个包装好的虚拟数据(RealData的虚拟数据)
*/
public class FutureData implements Data {
//既然FutureData是RealData对象的包装,那么久应该有一个对象的引用
private RealData realData = null;
//标注真实数据是否准备好
private boolean isReady = false;
//取数据时,如果RealData还没注入数据,则将阻塞等待
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void setRealData(RealData realData) {
while (isReady) {
//数据已经准备好,直接退出
return;
}
lock.lock();
try {
this.realData = realData;
this.isReady = true;
//数据已经准备,通知阻塞在getResult()上的请求
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* 获取真实数据,如果RealData代理对象没有准备好数据,则阻塞
*
* @return
*/
public String getResult() {
lock.lock();
try {
while (!isReady) {
//释放锁,同时阻塞
condition.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return realData.result;
}
}
/**
* Created with IntelliJ IDEA.
* User: zhouyonggui
* Date: 2018/12/29
* Time: 下午6:54
* Description: RealData是最终需要使用的数据,需要返回给FutureData
*/
public class RealData implements Data {
protected String result = null;
/**
* 在这个过程中,模拟数据包装
*
* @return
*/
public RealData(String param) {
StringBuffer sb = new StringBuffer();
//假设需要很长时间的业务处理
for (int i = 0; i < 10; i++) {
sb.append(param);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = sb.toString();
}
public String getResult() {
return result;
}
}
接下来就是client,内部主要实现了FutureData,并开启一个线程去构造RealData。在接受请求后,先返回一个FutureData对象,此时FutureData内部并没有真实数据,在需要使用数据时需要等待RealData构造完成,此时如果数据尚未准备好,则将阻塞直到有数据返回。
/**
* Created with IntelliJ IDEA.
* User: zyg
* Date: 2019/1/2
* Time: 下午9:12
* Description:FUture客户端主要负责获取FutureData,并异步起一个线程,构造RealData
*/
public class Client {
public Data request(final String queryStr) {
final FutureData future = new FutureData();
new Thread(new Runnable() {
public void run() {
RealData realData = new RealData(queryStr);
future.setRealData(realData);
}
}).start();
return future;
}
}
最后是我们的Main应用,她主要是负责调用client发起请求,并消费返回的数据。
/**
* Created with IntelliJ IDEA.
* User: zyg
* Date: 2019/1/2
* Time: 下午9:21
* Description:
*/
public class Main {
public static void main(String[] args) {
Client client = new Client();
//客户端发起请求
Data data = client.request("杨幂");
System.out.println("客户端请求完毕!");
//模拟其他业务
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//使用真实数据
System.out.println("数据=" + data.getResult());
}
}
以上是关于Future模式模拟的主要内容,如果未能解决你的问题,请参考以下文章