1. 前言
在讲future模式之前,需要先理解什么是同步,什么是异步?
- 同步:当任务a依赖于任务b的执行时,必须等待任务b执行完之后任务a才可以继续执行,此过程中任务a被阻塞,b也会被阻塞。可以类比我们打电话的场景(需要一直拿着电话)。
- 异步:任务a调用任务b,任务a并不需要一直等到任务b执行完毕,任务b只是返回一个虚拟的结果给任务a,然后任务a可以继续做其他事情,等到任务b执行完成之后在通知任务a(回调),或者任务a主动去请求任务b要结果,可以类比发短信的场景,(发一条短信后,过了好一会再看下有没有回复)。
2. Future模式举列
future模式就是异步的一种体现,举个例子,当我们发Ajax请求的时候,后台处理就属于异步的,它会先返回一个result给前端,同时进行后台数据处理等一系列操作,用户无需一直等待请求的结果,可以继续浏览或者操作其他内容。
image.png
package com.future;
public interface Data {
String getRequest();
}
package com.future;
public class RealData implements Data{
private String result ;
public RealData (String queryStr){
System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作..");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("操作完毕,获取结果");
result = "查询结果";
}
public String getRequest() {
return result;
}
}
package com.future;
public class FutureData implements Data{
/**
* 这个是真实数据的代理对象
* 和真实数据对象实现相同的接口,并且持有真实数据对象的引用
*/
private RealData realData;
private boolean isReady = false;
public synchronized void setRealData(RealData realData){
//如果已经装载完毕了,就直接返回
if(isReady){
return;
}
//装载真实的对象
this.realData = realData;
isReady = true;
//进行通知
notify();
}
public synchronized String getRequest() {
//如果没装载好,程序就一直处于阻塞状态
if(!isReady){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return this.realData.getRequest();
}
}
package com.future;
public class FutureClient {
public Data request(final String queryStr){
// 客户端请求,这时候只需要创建一个包装对象先返回给客户端
final FutureData futureData = new FutureData();
// 启动一个新的线程,去加载真实的数据,传递给这个代理对象
new Thread(
new Runnable() {
public void run() {
//在这个线程里可以慢慢的加载真实对象,然后传递给代理对象
RealData realData = new RealData(queryStr);
futureData.setRealData(realData);
}
}
).start();
//先把new出来的对象返回去
return futureData;
}
public static void main(String[] args) {
FutureClient fc = new FutureClient();
Data data = fc.request("请求参数");
System.out.println("请求发送成功");
System.out.println("做其他的事情...");
String result = data.getRequest();
System.out.println(result);
}
}
主线程调用request函数后不会阻塞,而是立即返回继续执行其他任务,再去查询之前request的结果。异步本质上还是开了多线程!!
网友评论