Future模式
假如有一個方法需要花費很長時間才能獲取運行結果,那麼,與其一直等待結果,不如先拿一張“提貨單”。
實例類圖:
Host類:
創建FutureData的實例
啓動一個新線程(相當於製作蛋糕的蛋糕店),用於創建RealData的實例
將FutureData的實例作爲返回值返回給調用者
其中future.setRealData(realdata);
相當於在顧客拿着提貨單來取貨之前製作蛋糕的過程。
public class Host {
public Data request(final int count,final char c){
System.out.println("request("+count+","+c+")begin");
//1創建FutrueData 的實例
final FutrueData future = new FutrueData();
//2啓動一個新線程,用於創建RealData的實例
new Thread(){
public void run(){
RealData realdata = new RealData(count, c);
future.setRealData(realdata);
}
}.start();
System.out.println("request("+count+","+c+")end" );
return future;
}
}
Data接口
public interface Data {
public abstract String getContent();
}
FutureData類:
表示提貨單的類
realData 用於保存稍後創建完的RealData實例
ready表示是否已經爲realData賦值的字段(true表示已賦值,蛋糕製作完成)
setRealData用於將RealData實例賦值給realData字段的方法,如果RealData創建完成,將ready設置true,notifyAll喚醒getContent(),getContent()方法未喚醒前無法取走蛋糕。
這裏的getContent()委託給了RealData類的getContent()
public class FutrueData implements Data{
private RealData realdata = null;
private boolean ready =false;
public synchronized void setRealData(RealData realdata){
if(ready){
return ;
}
this.realdata = realdata;
this.ready =true;
notifyAll();
}
@Override
public synchronized String getContent() throws ExecutionException {
while(!ready){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return realdata.getContent();
}
}
RealData類,需要花費長時間需要創建的實例的類(相當於蛋糕)
public class RealData implements Data {
private final String content;
public RealData(int count,char c){
System.out.println(" making RealData("+count+","+c+")begin");
char[] buffer = new char[count];
for(int i =0;i<count;i++){
buffer[i] = c;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(" making RealData("+count+","+c+")end");
this.content = new String(buffer);
}
@Override
public synchronized String getContent() {
// TODO Auto-generated method stub
return content;
}
}
Main類
測試執行類
public class Main {
public static void main(String[] args) {
System.out.println("main begin");
Host host = new Host();
Data data1 = host.request(10, 'A');
Data data2 = host.request(20, 'B');
Data data3 = host.request(30, 'C');
System.out.println(" main otherJob begin");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(" main otherJob end");
System.out.println("data1 = "+data1.getContent());
System.out.println("data2 = "+data2.getContent());
System.out.println("data3 = "+data3.getContent());
System.out.println("main END");
}
}
執行結果:
main begin
request(10,A)begin
request(10,A)end
request(20,B)begin
request(20,B)end
request(30,C)begin
request(30,C)end
main otherJob begin
making RealData(10,A)begin
making RealData(30,C)begin
making RealData(20,B)begin
main otherJob end
making RealData(10,A)end
data1 = AAAAAAAAAA
making RealData(20,B)end
data2 = BBBBBBBBBBBBBBBBBBBB
making RealData(30,C)end
data3 = CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
main END
總結:
Thread-Per-Message模式將消耗時間的處理交給其他線程,的確可以提高程序的響應性,但是在將處理轉交出去的時候,處理結果依然不知,這樣程序的響應性又會降低,使用Futrue模式,
首先編寫一個表示處理結果的RealData和具有相同接口的Future,接着處理開始時先返回Future,等到其他線程終止處理後,再將結果set到future,這樣Client可以使用Future角色獲取處理結果,這樣可以在不要降低響應性的前提下獲取處理結果。這就是Future模式。