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