1. 程式人生 > >每天一例多執行緒[day15]----Future模式之美麗的謊言

每天一例多執行緒[day15]----Future模式之美麗的謊言

Future模式的適用場景是:想要得到資料時,先返回資料的包裝,非同步獲取真實資料,真正需要時再拿資料,真實資料也許已經非同步得到,也許還在阻塞獲取中...

       這有點像BOSS佈置任務,比如由於市場需要,將在本月20號釋出一個版本,今天是10號,分配任務給小弟去做了,詢問小弟能不能搞定,由於小弟著急上位就答應了。而BOSS忙著處理每天的商務問題,在20號之前都沒有空理會給小弟分配的任務。

    不知不覺時間到了20號,這時BOSS趕忙詢問小弟做的到底如何了,其實這個時候小弟還差10%沒有搞定,但是不想影響自己以後的信譽就回答已經搞定了,準備晚上部署,BOSS拍了拍小弟肩膀說“好樣的!過一段給你加薪!”,BOSS走開後,小弟立刻拿出自己吃奶的力氣,最終在晚上部署前完成了任務。

     思想就是發起請求後會立即返回一個數據給你,但是這個資料只是個包裝,包裝資料會非同步請求真實資料,最終用的時候去拿真實的資料,可能非同步載入完成直接返回,也可能未完成阻塞著。

     再比如情人節到了,女朋友問你準備禮物了沒有,明明忘記了,但是依然說準備了,然後偷偷趕緊網購個,對吧!起碼事情算是圓滿了。

  1. public interface Data {

  2. String getRequest();

  3. }

  1. public class FutureData implements Data{

  2. private RealData realData ;

  3. private boolean isReady = false;

  4. public Thread currentThread;

  5. public synchronized void setRealData(RealData realData) {

  6. //如果已經裝載完畢了,就直接返回

  7. if(isReady){

  8. return;

  9. }

  10. //如果沒裝載,進行裝載真實物件

  11. this.realData = realData;

  12. isReady = true;

  13. //進行通知

  14. notify();

  15. }

  16. @Override

  17. public synchronized String getRequest() {

  18. //如果沒裝載好 程式就一直處於阻塞狀態

  19. while(!isReady){

  20. try {

  21. wait();

  22. } catch (InterruptedException e) {

  23. e.printStackTrace();

  24. }

  25. }

  26. //裝載好直接獲取資料即可

  27. return this.realData.getRequest();

  28. }

  29. }

  1. <code class="language-java">public class RealData implements Data{  
  2.     private String result ;  
  3.     public RealData (String queryStr){  
  4.         System.out.println("根據" + queryStr + "進行查詢,這是一個很耗時的操作..");  
  5.         try {  
  6.             Thread.sleep(5000);  
  7.         } catch (InterruptedException e) {  
  8.             e.printStackTrace();  
  9.         }  
  10.         System.out.println("操作完畢,獲取結果");  
  11.         result = "查詢結果";  
  12.     }  
  13.     @Override  
  14.     public String getRequest() {  
  15.         return result;  
  16.     }  
  17. }  
  18. </code>  
  1. public class FutureClient {

  2. public FutureData request(final String queryStr){

  3. //1 我想要一個代理物件(Data介面的實現類)先返回給傳送請求的客戶端,告訴他請求已經接收到,可以做其他的事情

  4. final FutureData futureData = new FutureData();

  5. //2 啟動一個新的執行緒,去載入真實的資料,傳遞給這個代理物件

  6. Thread t = new Thread(new Runnable() {

  7. @Override

  8. public void run() {

  9. //3 這個新的執行緒可以去慢慢的載入真實物件,然後傳遞給代理物件

  10. RealData realData = new RealData(queryStr);

  11. futureData.setRealData(realData);

  12. }

  13. });

  14. t.start();

  15. futureData.currentThread = t;

  16. return futureData;

  17. }

  18. }

  1. public class Main {

  2. public static void main(String[] args) throws InterruptedException {

  3. FutureClient fc = new FutureClient();

  4. FutureData data = fc.request("請求引數");

  5. System.out.println("請求傳送成功!");

  6. System.out.println("做其他的事情..."+"請求資料執行緒狀態:"+data.currentThread.getState());

  7. //經測試程式碼阻塞在這一行,等待獲取真實資料,而 以上程式碼則實時執行

  8. String result = data.getRequest();

  9. System.out.println(result+"請求資料的執行緒狀態:"+data.currentThread.getState());

  10. }