在JAVA平臺(tái),實(shí)現(xiàn)異步調(diào)用的角色有如下三個(gè)角色:
調(diào)用者 取貨憑證 真實(shí)數(shù)據(jù)
一個(gè)調(diào)用者在調(diào)用耗時(shí)操作,不能立即返回?cái)?shù)據(jù)時(shí),先返回一個(gè)取貨憑證.然后在過一斷時(shí)間后
憑取貨憑證來獲取真正的數(shù)據(jù).
所以連結(jié)調(diào)用者和真實(shí)數(shù)據(jù)之間的橋梁是取貨憑證.我們先來看它的實(shí)現(xiàn):
public class FutureTicket{
private Object data = null;
private boolean completed = false;
public synchronized void makeRealData(){
if(this.complited) return;
//獲取數(shù)據(jù)的耗時(shí)操作.這里用Sleep代替
try{
Thread.sleep(10000);
}catch(Throwable t){}
this.data = "返回的數(shù)據(jù)內(nèi)容";
this.completed = true;
notifyAll();
}
public synchronized Object getData(){
while(!this.completed)){
try{
wait();
}catch(Throwable t){}
}
return this.data;
}
public boolean isCompleted(){
return this.completed;
}
}
為了簡(jiǎn)單化說明(不把它們的關(guān)系開得復(fù)雜),這里用Objectb代替了真實(shí)數(shù)據(jù).而真實(shí)的實(shí)現(xiàn)中
我們應(yīng)該把makeData放在一個(gè)真實(shí)數(shù)據(jù)的類中,然后提供一個(gè)方法返回真實(shí)數(shù)據(jù).這樣對(duì)于真實(shí)
數(shù)據(jù)的處理和取貨憑證解耦.
對(duì)于這個(gè)取貨憑證,調(diào)用者的如何調(diào)用是異步調(diào)用的關(guān)鍵:
publc class Requester{
public FutureTicket request(){
final FutureTicket ft = new FutureTicket();
//在新線程中調(diào)用耗時(shí)操作
new Thread(){
public void run(){
ft.makeRealData();
}
}.start();
return ft;
}
}
在新線程中啟動(dòng)耗時(shí)操作后,不等待線程的完成立即返回提貨單.
然后調(diào)用者可以根據(jù)ft.isCompleted()來調(diào)用getData()獲取真實(shí)數(shù)據(jù).
當(dāng)然對(duì)ft.isCompleted()測(cè)試可以按規(guī)定時(shí)間間隔輪巡(極低級(jí)的方案),也可以
在條件不滿足時(shí)wait(),然后等待makeData的notifyAll();這樣你就完成了一個(gè)
用JAVA模擬的異步操作.
改進(jìn):
但這樣的調(diào)用對(duì)于調(diào)用者來說仍然要繼續(xù)控制線程操作.如果調(diào)用者是一個(gè)資深的
程序員,這當(dāng)然沒有問題.但假如我們把對(duì)直接數(shù)據(jù)的處理委托給取貨憑證來做.調(diào)用
者直接規(guī)定對(duì)數(shù)據(jù)的操作,然后由取貨憑證來調(diào)用規(guī)定的操作,這對(duì)于調(diào)用者是一個(gè)很
好的解脫:
interface ProcessData{
public void process(Onject data);
}
public MyProcessData{
public void process(Object data){
//你不管什么時(shí)候起初數(shù)據(jù)data被獲取了.
//你只要規(guī)定如果獲取到數(shù)據(jù)了如何處理
System.out.println(data.toString() + "處理完成...........");
//insert into dataBase?
}
}
取貨憑證在接收調(diào)用者請(qǐng)求獲取數(shù)據(jù)時(shí),要知道對(duì)獲取的數(shù)據(jù)如何處理的方法:
public class FutureTicket{
private Object data = null;
private boolean completed = false;
private ProcessData pd;
public FutureTicket(ProcessData pd){
this.pd = pd;
}
public synchronized void makeRealData(ProcessData pd){
if(this.complited) return;
//獲取數(shù)據(jù)的耗時(shí)操作.這里用Sleep代替
try{
Thread.sleep(10000);
}catch(Throwable t){}
this.data = "返回的數(shù)據(jù)內(nèi)容";
this.completed = true;
notifyAll();
}
public synchronized void putData(){
while(!this.completed)){
try{
wait();
}catch(Throwable t){}
}
//return this.data;
//不用返回了,直接處理
this.pd.process(this.data);
// alert(?);
}
//這個(gè)方法也可以不要了.
public boolean isCompleted(){
return this.completed;
}
}
調(diào)用:
final