John Jiang

          a cup of Java, cheers!
          https://github.com/johnshajiang/blog

             :: 首頁(yè) ::  :: 聯(lián)系 :: 聚合  :: 管理 ::
            131 隨筆 :: 1 文章 :: 530 評(píng)論 :: 0 Trackbacks
          使用Callable返回結(jié)果
              本文是Sun官方以Blog形式發(fā)布的Java核心技術(shù)竅門(JavaCoreTechTip)中的一個(gè)。本文主要介紹了Callable及其相關(guān)接口和類的使用,篇幅不長(zhǎng)且易于理解,故翻譯在了此處,相信對(duì)于準(zhǔn)備或剛接觸java.util.concurrent的朋友會(huì)有所幫助。(2008.05.31最后更新)

              自從Java平臺(tái)的最開始,Runnable接口就已存在了。它允許你定義一個(gè)可由線程完成的任務(wù)。如大多數(shù)人所已知的那樣,它只提供了一個(gè)run方法,該方法既不接受任何參數(shù),也不返回任何值。如果你需要從一個(gè)未完成的任務(wù)中返回一個(gè)值,你就必須在該接口之外使用一個(gè)方法去等待該任務(wù)完成時(shí)通報(bào)的某種消息。例如,下面的示例就是你在這種情景下可能做的事情:
              Runnable runnable = ...;
              Thread t = new Thread(runnable);
              t.start();
              t.join();
              String value = someMethodtoGetSavedValue()
          嚴(yán)格來(lái)說(shuō),上述代碼并無(wú)錯(cuò)誤,但現(xiàn)在可用不同的方法去做,這要感謝J2SE 5.0引入的Callable接口。不同于Runnable接口擁有run方法,Callable接口提供的是call方法,該方法可以返回一個(gè)Object對(duì)象,或可返回任何一個(gè)在泛型化格式中定義了的特定類型的對(duì)象。
              public interface Callable<V> {
                 V call() throws Exception;
              }
          因?yàn)槟悴豢赡馨袰allable對(duì)象傳到Thread對(duì)象去執(zhí)行,你可換用ExecutorService對(duì)象去執(zhí)行Callable對(duì)象。該服務(wù)接受Callable對(duì)象,并經(jīng)由submit方法去執(zhí)行它。
              <T> Future<T> submit(Callable<T> task)
          如該方法的定義所示,提交一個(gè)Callable對(duì)象給ExecutorService會(huì)返回一個(gè)Future對(duì)象。然后,F(xiàn)uture的get方法將會(huì)阻塞,直到任務(wù)完成。
              為了證明這一點(diǎn),下面的例子為命令行中的每個(gè)詞都創(chuàng)建一個(gè)單獨(dú)的Callable實(shí)例,然后把這些詞的長(zhǎng)度加起來(lái)。各個(gè)Callable對(duì)象將只是計(jì)算它自己的詞的長(zhǎng)度之和。Futures對(duì)象的Set集合將被保存以便從中獲得計(jì)算用的值。如果需要保持返回值的順序,則可換用一個(gè)List對(duì)象。

          import java.util.*;
          import java.util.concurrent.*;

          public class CallableExample {

              
          public static class WordLengthCallable
                      
          implements Callable {
                  
          private String word;
                  
          public WordLengthCallable(String word) {
                      
          this.word = word;
                  }
                  
          public Integer call() {
                      
          return Integer.valueOf(word.length());
                  }
              }

              
          public static void main(String args[]) throws Exception {
                  ExecutorService pool 
          = Executors.newFixedThreadPool(3);
                  Set
          <Future<Integer>> set = new HashSet<Future&lg;Integer>>();
                  
          for (String word: args) {
                      Callable
          <Integer> callable = new WordLengthCallable(word);
                      Future
          <Integer> future = pool.submit(callable);
                      set.add(future);
                  }
                  
          int sum = 0;
                  
          for (Future<Integer> future : set) {
                      sum 
          += future.get();
                  }
                  System.out.printf(
          "The sum of lengths is %s%n", sum);
                  System.exit(sum);
              }
          }
          WordLengthCallable保存了每個(gè)詞并使用該詞的長(zhǎng)度作為call方法的返回值。這個(gè)值可能會(huì)花點(diǎn)兒時(shí)間去生成,不過(guò)在這個(gè)例子中,可以立即知道它。 call方法的唯一要求是這個(gè)值要在call方法的結(jié)尾處返回。當(dāng)Future的get方法稍后被調(diào)用時(shí),如果任務(wù)運(yùn)行得很快的話,F(xiàn)uture將會(huì)自動(dòng)得到這個(gè)值(如同本例的情況),否則將一直等到該值生成完畢為止。多次調(diào)用get方法不會(huì)導(dǎo)致任務(wù)從該線程返回。因?yàn)樵摮绦虻哪康氖怯?jì)劃所有字的長(zhǎng)度之和,它不會(huì)強(qiáng)令Callable任務(wù)結(jié)束。如果最后一個(gè)任務(wù)在前三個(gè)任務(wù)之前完成,也是沒(méi)錯(cuò)的。對(duì)Future的get方法的第一次調(diào)用將只會(huì)等待Set中第一個(gè)任務(wù)結(jié)束,而不會(huì)阻塞其它的任務(wù)分別執(zhí)行完畢。它只會(huì)等待當(dāng)次線程或任務(wù)結(jié)束。這個(gè)特定的例子使用固定數(shù)線程池來(lái)產(chǎn)生ExecutorService對(duì)象,但其它有效的方法也是可行的。
              關(guān)于執(zhí)行器和線程池用法的更多信息,請(qǐng)見Java Tutorial中Executors一節(jié)。SwingWorker類是另一個(gè)使用Future的Runnable對(duì)象的例子,盡管有些微不同之處。更多信息請(qǐng)見Java Tutorial中Worker Threads and SwingWorker一節(jié)。

          posted on 2008-05-31 22:24 John Jiang 閱讀(3854) 評(píng)論(0)  編輯  收藏 所屬分類: JavaSEJavaConcurrency翻譯CoreJavaTechTips
          主站蜘蛛池模板: 通海县| 钟祥市| 孝昌县| 马鞍山市| 兴文县| 成武县| 克什克腾旗| 涿鹿县| 清丰县| 衡山县| 开远市| 安化县| 新乡市| 吴川市| 香格里拉县| 高雄市| 锡林郭勒盟| 辉县市| 长兴县| 都兰县| 汉沽区| 五峰| 台东市| 化州市| 石家庄市| 安康市| 石狮市| 儋州市| 涡阳县| 垫江县| 嘉定区| 乃东县| 泰来县| 昌宁县| 五峰| 云龙县| 彰化市| 固原市| 依兰县| 伊川县| 汝南县|