java多線程模式之 Future模式

 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,等到其他線程終止處理後,再將結果setfuture,這樣Client可以使用Future角色獲取處理結果,這樣可以在不要降低響應性的前提下獲取處理結果。這就是Future模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章