当调用者调用耗时操作时,无需一直等待,先得到提货单,过段时间通过提货单获取真实数据
实现异步调用的角色有如下三个角色:调用者、接收者、提货单、真实数据
为了能够更好的理解,现有一个场景:
去蛋糕店买蛋糕,不需要等蛋糕做出来(假设现做要很长时间),只需要领个提货单就可以了(去干别的事情),等到蛋糕做好了,再拿提货单取蛋糕就可以了。
/**
* 模拟客户(d1、d2、d3)订蛋糕请求,返回得到FutureData(提货单)
* 之后,客户不用一直等待蛋糕(RealData)忙自己该忙的事
* 做完其它事情后再取蛋糕
*/
public class Caller {
public static void main(String[] args){
Receiver receiver = new Receiver();
Data d1 = receiver.request();//订蛋糕请求
Data d2 = receiver.request();
Data d3 = receiver.request();
try {
Thread.sleep(3000); //模拟客户做其它事情
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(d1.getContent());//取蛋糕(RealData)
System.out.println(d2.getContent());
System.out.println(d3.getContent());
}
}
/**
* Receiver 接受者:相当于场景中的当蛋糕店,接收到客户(Caller)订单request,
* 服务员首先开订单证明(提货单:FutureData)给客户,客户过段时间再来取蛋糕(RealData)
* 开启线程make RealData
*/
public class Receiver {
public Data request(){
final FutureData future = new FutureData();
new Thread(){
public void run(){
RealData realdata = new RealData();
future.setRealData(realdata);
}
}.start();
return future;
}
}
/**
* FutureData:提货单
* 蛋糕做完调用setRealData
* 客户getContent获取蛋糕,如果蛋糕没有做好,继续等待,直到蛋糕做好
*/
public class FutureData implements Data {
private RealData realdata = null;
private boolean ready = false;
public synchronized String getContent() {
while(!ready){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return realdata.getContent();
}
public synchronized void setRealData(RealData realdata) {
this.realdata = realdata;
this.ready = true;
notifyAll();
}
}
public class RealData implements Data {
private String content;
/**
* 睡眠5秒模仿做蛋糕
*/
public RealData(){
System.out.println("begin making RealData");
try {
System.out.println("RealData processing");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("RealData maked");
this.content="真材实料";
}
public String getContent() {
return content;
}
}
每个线程只是专门负责制作特定顾客所需要的“蛋糕”。也就是顾客A对应着蛋糕师傅A,顾客B对应着蛋糕师傅B。即使顾客B的蛋糕被先做好了,顾客A也只能等待蛋糕师傅A把蛋糕做好。换句话说,顾客之间没有竞争关系。