新的起點 新的開始

          快樂生活 !

          深入淺出多線程(3)-Future異步模式以及在JDK1.5Concurrent包中的實現

             接深入淺出多線程(2)在多線程交互的中,經常有一個線程需要得到另個一線程的計算結果,我們常用的是Future異步模式來加以解決。
             什么是Future模式呢?Future 顧名思義,在金融行業叫期權,市場上有看跌期權和看漲期權,你可以在現在(比如九月份)購買年底(十二月)的石油,假如你買的是看漲期權,那么如果石油真的漲了,你也可以在十二月份依照九月份商定的價格購買。扯遠了,Future就是你可以拿到未來的結果。對于多線程,如果線程A要等待線程B的結果,那么線程A沒必要等待B,直到B有結果,可以先拿到一個未來的Future,等B有結果是再取真實的結果。其實這個模式用的很多,比如瀏覽器下載圖片的時候,剛開始是不是通過模糊的圖片來代替最后的圖片,等下載圖片的線程下載完圖片后在替換。如圖所示:


          • 在沒有JDK1.5提供的Concurrent之前,我們通過自定義一個結果類,負責結果持有。
          如下面代碼:
          package vincent.blogjava.net;

          public class FutureResult {
              
          private String result;
              
          private boolean isFinish =false;
              
          public String getResult() {
                  
          return result;
              }
              
          public synchronized void setResult(String result) {
                  
          this.result = result;
                  
          this.isFinish = true;
              }
              
          public synchronized boolean isFinish() {
                  
          return isFinish;
              }

          }
          存儲結果值和是否完成的Flag。
          package vincent.blogjava.net;

          public class GenerateResultThread extends Thread{
              FutureResult fr ;
              
          public GenerateResultThread(FutureResult fr ){
                  
          this.fr = fr;
              }
              
          public  void run(){
                  
          //模仿大量耗時計算后(5s)返回結果。
                  try {
                      System.out.println(
          "GenerateResultThread開始進行計算了!");
                      Thread.sleep(
          5000);
                  } 
          catch (InterruptedException e) {
                      
          // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
                  fr.setResult(
          "ResultByGenerateResultThread");
              }
          }
          計算具體業務邏輯并放回結果的線程。
          package vincent.blogjava.net;

          public class Main {

              
          /**
               * 
          @param args
               * 
          @throws InterruptedException 
               
          */
              
          public static void main(String[] args) throws InterruptedException {
                  
          // TODO Auto-generated method stub
                 FutureResult fr = new FutureResult();
                 
          new GenerateResultThread(fr).start();
                 
          //main線程無需等待,不會被阻塞。
                 
          //模仿 干自己的活 2s。
                 Thread.sleep(2000);
                 
          // 估計算完了吧 取取試試。
                 System.out.println("過來2s了,看看有結果嗎?");
                 
          if(!fr.isFinish()){System.out.println("還沒有完成呢! 繼續干自己活吧!");}
                 
          //模仿 干自己的活 4s。
                 Thread.sleep(4000);
                 System.out.println(
          "過來4s了,看看有結果嗎?");
                 
          if(fr.isFinish()){
                     System.out.println(
          "完成了!");
                     System.out.println(
          "Result:"+fr.getResult());
                     
                 }
              }

          }
          Main方法需要GenerateResultThread線程計算的結果,通過這種模式,main線程不需要阻塞。結果如下:
          GenerateResultThread開始進行計算了!
          過來2s了,看看有結果嗎?
          還沒有完成呢! 繼續干自己活吧!
          過來4s了,看看有結果嗎?
          完成了!
          Result:ResultByGenerateResultThread
          •  在JDK1.5 Concurrent 中,提供了這種Callable的機制。我們只要實現Callable接口中的Call方法,Call方法是可以返回任意類型的結果的。如下:
          package vincent.blogjava.net;

          import java.util.concurrent.Callable;
          import java.util.concurrent.ExecutionException;
          import java.util.concurrent.Future;
          import java.util.concurrent.FutureTask;

          public class ConcurrentImpl {

          public static void main(String[] args) throws InterruptedException, Exception {
              FutureTask  fr 
          = new FutureTask(new Returnresult());
              
          new Thread(fr).start();
                 
          //main線程無需等待,不會被阻塞。
                 
          //模仿 干自己的活 2s。
                 Thread.sleep(2000);
                 
          // 估計算完了吧 取取試試。
                 System.out.println("過來2s了,看看有結果嗎?");
                 
          if(!fr.isDone()){System.out.println("還沒有完成呢! 繼續干自己活吧!");}
                 
          //模仿 干自己的活 4s。
                 Thread.sleep(4000);
                 System.out.println(
          "過來4s了,看看有結果嗎?");
                 
          if(fr.isDone()){
                     System.out.println(
          "完成了!");
                     System.out.println(
          "Result:"+fr.get());
          }
          }
          }
          class Returnresult implements Callable{

              @Override
              
          public Object call() throws Exception {
                  
          //模仿大量耗時計算后(5s)返回結果。
                  System.out.println("GenerateResultThread開始進行計算了!");
                  Thread.sleep(
          11000);
                  
          return "ResultByGenerateResultThread";
              }
              
          }
          Returnresult 實現了Callable接口,在Call方法中實現業務邏輯,并返回結果。在Main方法里面,初始化FutureTask 并將該Task作為Runnable加入Thread后,啟動線程。得到跟剛才相同的效果。
          注意: 通過JDK標準的Future后,沒有必要增加額外的Object來只有Result,更加簡單明了,同時FutureTask還提供了Cancel的功能,我們持有FutureTask引用后可以Cancel該線程。通過get()取值是,如果結果還沒有返回,將會阻塞Main線程。

          •   其實JDK 實現Future模式的秘密就在FutureTask類里:
          FutureTask是實現了Future 和Runnable,對了就是Runnbale接口,我們就可以把它構造到Thread里,啟動執行了。
          看看,當 new Thread(new FutureTask(new Callable())).start 時:
          看圖:
          G
          get 方法取result值,FutureTask 提供Timeout 功能,如果超時,拋出異常。


          posted on 2008-09-03 00:57 advincenting 閱讀(2637) 評論(4)  編輯  收藏

          評論

          # re: 深入淺出多線程(3)-Future異步模式以及在JDK1.5Concurrent包中的實現[未登錄] 2008-09-03 08:40 tester

          好文  回復  更多評論   

          # re: 深入淺出多線程(3)-Future異步模式以及在JDK1.5Concurrent包中的實現 2008-09-03 08:53 denni

          寫的深入淺出,很好  回復  更多評論   

          # re: 深入淺出多線程(3)-Future異步模式以及在JDK1.5Concurrent包中的實現 2008-09-03 18:15 Jack.Wang

          雖然東西很簡單,但寫的很認真!很好!  回復  更多評論   

          # re: 深入淺出多線程(3)-Future異步模式以及在JDK1.5Concurrent包中的實現 2009-02-12 17:24 wego

          不錯!我試了一下,很好!  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          公告

          Locations of visitors to this pageBlogJava
        1. 首頁
        2. 新隨筆
        3. 聯系
        4. 聚合
        5. 管理
        6. <2008年9月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          統計

          常用鏈接

          留言簿(13)

          隨筆分類(71)

          隨筆檔案(179)

          文章檔案(13)

          新聞分類

          IT人的英語學習網站

          JAVA站點

          優秀個人博客鏈接

          官網學習站點

          生活工作站點

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 陇川县| 临西县| 天气| 南涧| 河南省| 嘉定区| 洪江市| 石台县| 德昌县| 钦州市| 湖口县| 徐水县| 叶城县| 常山县| 大名县| 普安县| 锡林郭勒盟| 长岛县| 广安市| 壶关县| 彝良县| 洛浦县| 松江区| 彭州市| 青龙| 东至县| 太康县| 台湾省| 阿坝| 永春县| 古丈县| 梧州市| 边坝县| 银川市| 通渭县| 波密县| 龙州县| 柳江县| 汤原县| 乌兰浩特市| 芮城县|