在JAVA平台实现异步调用的角色有如下三个角色:调用者 提货单 真实数据一个调用者在调用耗时操作不能立即返回数据时先返回一个提货单然后在过一断时间后凭提货单来获取真正的数据去蛋糕店买蛋糕不需要等蛋糕做出来(假设现做要很长时间)只需要领个提货单就可以了(去干别的事情)等到蛋糕做好了再拿提货单取蛋糕就可以了public class Main { public static void main(String[] args) {
Systemoutprintln(main BEGIN);
Host host = new Host();
Data data = hostrequest( A);
Data data = hostrequest( B);
Data data = hostrequest( C);
Systemoutprintln(main otherJob BEGIN);
try {
Threadsleep();
} catch (InterruptedException e) {
}
Systemoutprintln(main otherJob END);
Systemoutprintln(data = + datagetContent());
Systemoutprintln(data = + datagetContent());
Systemoutprintln(data = + datagetContent());
Systemoutprintln(main END);
}
}
这里的main类就相当于顾客host就相当于蛋糕店顾客向蛋糕店定蛋糕就相当于发请求request返回的数据data是FutureData的实例就相当于提货单而不是真正的蛋糕在过一段时间后(sleep一段时间后)调用datagetContent()也就是拿提货单获取执行结果
下面来看一下顾客定蛋糕后蛋糕店做了什么
public class Host {
public Data request(final int count final char c) {
Systemoutprintln(request( + count + + c + ) BEGIN);
// () 建立FutureData的实体
final FutureData future = new FutureData();
// () 为了建立RealData的实体启动新的线程
new Thread() {
public void run() {
//在匿名内部类中使用countfuturec
RealData realdata = new RealData(count c);
futuresetRealData(realdata);
}
}start();
Systemoutprintln(request( + count + + c + ) END);
// () 取回FutureData实体作为传回值
return future;
}
}
host(蛋糕店)在接到请求后先生成了提货单FutureData的实例future然后命令蛋糕师傅RealData去做蛋糕realdata相当于起个线程去做蛋糕了然后host返回给顾客的仅仅是提货单future而不是蛋糕当蛋糕做好后蛋糕师傅才能给对应的提货单蛋糕也就是futuresetRealData(realdata)
下面来看看蛋糕师傅是怎么做蛋糕的
建立一个字符串包含count个c字符为了表现出犯法需要花费一些时间使用了sleep
public class RealData implements Data { private final String content;
public RealData(int count char c) {
Systemoutprintln(making RealData( + count + + c + ) BEGIN);
char[] buffer = new char[count];
for (int i = ; i < count; i++) {
buffer[i] = c;
try {
Threadsleep();
} catch (InterruptedException e) {
}
}
Systemoutprintln(making RealData( + count + + c + ) END);
ntent = new String(buffer);
}
public String getContent() {
return content;
}
}
现在来看看提货单future是怎么与蛋糕content对应的:
public class FutureData implements Data { private RealData realdata = null;
private boolean ready = false;
public synchronized void setRealData(RealData realdata) {
if (ready) {
return; // 防止setRealData被调用两次以上
}
thisrealdata = realdata;
thisready = true;
notifyAll();
}
public synchronized String getContent() {
while (!ready) {
try {
wait();
} catch (InterruptedException e) {
}
}
return realdatagetContent();
}
}
顾客做完自己的事情后会拿着自己的提货单来取蛋糕
Systemoutprintln(data = + datagetContent());
这时候如果蛋糕没做好就只好等了
while (!ready) { try {
wait();
} catch (InterruptedException e) {
}
//等做好后才能取到
return realdatagetContent();
程序分析
对于每个请求host都会生成一个线程这个线程负责生成顾客需要的蛋糕在等待一段时间以后如果蛋糕还没有做好顾客还必须等待直到蛋糕被做好也就是
futuresetRealData(realdata); 执行以后顾客才能拿走蛋糕
每个线程只是专门负责制作特定顾客所需要的蛋糕也就是顾客A对应着蛋糕师傅A顾客B对应着蛋糕师傅B即使顾客B的蛋糕被先做好了顾客A也只能等待蛋糕师傅A把蛋糕做好换句话说顾客之间没有竞争关系
类FutureData的两个方法被设置为synchronized实际上蛋糕师傅A与顾客A之间的互斥关系也就是顾客A必须等待蛋糕师傅A把蛋糕做好后才能拿走而与蛋糕师傅B是否做好了蛋糕没有关系