Future模式:核心在于,省去了客户端程序的等待时间,这段时间可以去处理其他逻辑,待一段时间后检查服务端程序有没有准备好。
面写了一个例子:
客户端发起一个请求字串,服务端立马处理得到订单号即图中3:call_return,然后去处理其他逻辑,服务端Future封装了真实Data的代理也就是图中的2:other_call,待处理好后,客户端发起getResult()请求,返回结果。
代码如下:
公共接口:
package com.hanchun.future;
//数据接口,FutureData实现
public interface Data {
public String getResult();
public boolean ifSuccess();
}
Client端
package com.hanchun.future;
//client实现获取FutureData
public class Client {
public Data request(final String queryStr){
final FutureData future = new FutureData(queryStr);
//为什么要新开一个线程? 开启线程后,不会阻塞在此
new Thread(){
public void run(){
//访问真实的构造方法
RealData realData = new RealData(queryStr);
future.setRealData(realData); //构造完成,放入代理中
}
}.start();
return future; //FutureData 会立即返回
}
}
Future模式的关键,是获取RealData的代理,封装了获取RealData的等待过程
package com.hanchun.future;
//不是最终要返回的数据,是真实数据的[代理],封装了等待RealData的等待过程
public class FutureData implements Data {
//持有RealData引用
protected RealData realData = null;
//标志位,服务端是否准备好数据
protected boolean isReady = false;
protected String preResult;
public FutureData(String para) {
preResult = "PRE" + para;
}
public String preHanding(){
return preResult;
}
//真实数据的[代理]
public synchronized void setRealData(RealData realData){
//如果准备好,直接返回,健壮性考虑
if(isReady){
return;
}
this.realData = realData;
isReady = true;
//将getResult()方法中的wait唤醒
notifyAll();
}
public synchronized String getResult() {
//阻塞,一直等待,直到获得到了真实数据返回
while(!isReady){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return realData.result;
}
@Override
public boolean ifSuccess() {
return isReady;
}
}
package com.hanchun.future;
public class RealData {
protected final String result;
//构造方法
public RealData(String para){
//realData构造可能很慢,暂时用sleep模拟
System.out.println("服务端正在处理具体逻辑。。。"); //for debug
try{
//sleep代替实际的业务流程
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
result = "TRUE" + para;
}
}
程序入口:
package com.hanchun.future;
public class Main {
public static void main(String[] args) {
Client client = new Client();
//这里会立即返回,是FutureData不是RealData
//客户端发起请求
System.out.println("客户端发起请求,参数pre_order_no(预订单号) 123456");//for debug
Data data = client.request("123456");
//是否数据全部处理完,如果没有,先返回预处理数据
if(!data.ifSuccess()){
System.out.println("请求完毕,服务端正在处理数据,预订单号:" + ((FutureData)data).preResult); //for debug
}
try{
//client可以在这段时间去处理其他逻辑
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("[服务端]返回数据" + data.getResult()); //for debug
}
}
程序运行结果:
客户端发起请求,参数pre_order_no(预订单号) 123456
请求完毕,服务端正在处理数据,预订单号:PRE123456
服务端正在处理具体逻辑。。。
[服务端]返回数据TRUE123456
package com.hanchun.future.jdk;
import java.util.concurrent.ExecutionException;
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 InterruptedException, ExecutionException {
//FutureTask,作为单独线程运行
FutureTask<String> future = new FutureTask<String>(new RealData("123456"));
ExecutorService executor = Executors.newFixedThreadPool(1); //Executors起一个固定线程,多在服务器编程使用
executor.submit(future);
//执行FutureTask相当于前面的client.request("123456");
//开启线程进行RealData的call()执行
System.out.println("请求完毕");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//相当于前面的data.getResult(), 取得call()返回的值
//如果call方法没有完成,就一直等待
System.out.println("真实数据:"+ future.get());
}
}
package com.hanchun.future.jdk;
import java.util.concurrent.Callable;
//实现Callable接口,实现具体的业务逻辑
public class RealData implements Callable<String> {
public String para;
public RealData(String para) {
this.para = para;
}
@Override
public String call() throws Exception {
//这里是真实的业务逻辑,用sleep()来代替
System.out.println("正在处理数据。。。"); //for debug
Thread.sleep(1000);
return "TURE" + para;
}
}