神奇好望角 The Magical Cape of Good Hope

          庸人不必自擾,智者何需千慮?
          posts - 26, comments - 50, trackbacks - 0, articles - 11
            BlogJava :: 首頁 ::  :: 聯系 :: 聚合  :: 管理

          2012年2月9日

          21 世紀初,Spring 框架的誕生和崛起讓沉重而腐朽的 J2EE 遭到了當頭棒喝,隨后大批開發人員轉投 Spring 陣營,呼吸間就讓 J2EE 陣營大傷元氣。然而這種命懸一線的危機并沒有造成毀滅性的打擊,尤其是對于 Java 這種提倡開放的平臺而言,取長補短,互相促進才是正道。于是,JCP 委員會痛定思痛,在 2006 年推出 Java EE 5 規范,主要是對 EJB 的開發進行了極大幅度的簡化。2008 年發布的 Java EE 6 引入了 CDI、BV、JAX-RS 等一系列新功能,并且以配置文件(profile)的方式讓 Java EE 向輕量級邁進了一步。特別有趣的是,Spring 框架也開始提供對某些 Java EE 注解的支持,是否標志著兩大陣營開始合流?Java EE 7 預定于今年下半年發布,目標是支持云計算。最近幾年來,云計算一直被炒作,卻從來沒有一個準確的定義和規范,希望 Java EE 7 能夠在 Java 界扭轉這種尷尬的局面。

          下面開始詳細列舉 Java EE 7 的新功能前瞻,數據來源于《Java Magazine 2012-01/02》中的《Cloud/Java EE: Looking Ahead to Java EE 7》一文。Java EE 7 是以“日期驅動”的方式開發的,也就是說,在計劃日期到達前沒有完成的功能都將被推遲到 Java EE 8。

          Java EE 7(JSR-342)

          • 主題:讓應用程序能夠在私有或公共云上容易地運行。
          • 該平臺將定義一個應用程序元數據描述符,以描述 PaaS 執行環境(例如多租戶、資源共享、服務質量,以及應用程序間的依賴)。
          • 支持 HTML5、WebSocket、JSON 等新標準,并為它們一一提供 API。
          • 消除受管 Bean、EJB、Servlet、JSF、CDI 和 JAX-RS 之間不一致的地方。
          • 可能在 Web 配置文件中包含 JAX-RS 2.0 和 JMS 2.0 API 修訂版。
          • 更新一些現有的技術,可能引入用于 Java EE 的并發工具(JSR-236)和 JCache(JSR-107)。

          Java Persistence 2.1(JSR-338)

          • 支持多租戶。
          • 支持存儲過程和廠商函數。
          • 用規則(Criteria)進行更新和刪除。
          • 支持數據庫大綱(Scheme)的生成。
          • 持久化上下文的同步。
          • 偵聽器中的 CDI 注入。

          JAX-RS 2.0: The Java API for RESTful Web Services(JSR-339)

          • 客戶端 API——底層使用構建者模式,可能提供上層封裝。
          • 超媒體——輕松創建和處理關聯了資源的鏈接。
          • 使用 Bean 驗證框架來驗證表單或查詢參數。
          • @Inject 更緊密集成。
          • 服務端的異步請求處理。
          • 使用“qs”進行服務端的內容協商。

          Java Servlet 3.1(JSR-340)

          • 為 Web 應用程序優化 PaaS 模型。
          • 用于安全、會話和資源的多租戶。
          • 基于 NIO2 的異步 I/O。
          • 簡化的異步 Servlet。
          • 利用 Java EE 并發工具。
          • 支持 WebSocket。

          Expression Language 3.0(JSR-341)

          • ELContext 分離為解析和求值上下文。
          • 可定制的 EL 強迫規則。
          • 在 EL 表達式中直接引用靜態方法和成員。
          • 添加運算符,例如等于、字符串連接和取大小。
          • 與 CDI 集成,例如在表達式求值前/中/后生成事件。

          Java Message Service 2.0(JSR-343)

          • 簡化開發——改變 JMS 編程模型,讓應用程序開發變得更加簡單容易。
          • 清除/澄清現有規范中的模糊之處。
          • 與 CDI 集成。
          • 澄清 JMS 和其他 Java EE 規范之間的關系。
          • 新的強制性 API允許任何 JMS 提供者能與任何 Java EE 容器集成。
          • 來自平臺的多租戶和其他云相關的功能。

          JavaServer Faces 2.2(JSR-344)

          • 簡化開發——使配置選項動態化,使復合組件中的 cc:interface 可選,Facelet 標記庫的速記 URL,與 CDI 集成,JSF 組件的 OSGi 支持。
          • 支持 Portlet 2.0 橋(JSR-329)的實現。
          • 支持 HTML5 的功能,例如 HTML5 表單、元數據、頭部和區段內容模型。
          • 流管理,頁面導航事件的偵聽器,以及 fileUploadBackButton 等新組件。

          Enterprise JavaBeans 3.2(JSR-345)

          • 增強 EJB 架構以支持 PaaS,例如多租戶。
          • 對在 EJB 外使用容器管理的事務進行工廠化。
          • 更進一步使用注解。
          • 與平臺中的其他規范對齊和集成。

          Contexts and Dependency Injection 1.1(JSR-346)

          • 攔截器的全局排序和管理內建上下文的裝飾器 API。
          • 可在 Java EE 容器外啟動的嵌入式模式。
          • 聲明式地控制歸檔中的哪些包和 Bean 將被掃描。
          • 注入日志之類的靜態成員。
          • 將 Servlet 事件作為 CDI 事件發送。

          Bean Validation 1.1(JSR-349)

          • 與其他 Java EE 規范集成。
          • JAX-RS:在 HTTP 調用中驗證參數和返回值。
          • JAXB:將約束條件轉換到 XML 模式描述符中。
          • 方法級別的驗證。
          • 在組集合上應用約束條件。
          • 擴展模型以支持“與”和“或”風格的組合。

          JCache: Java Temporary Caching API(JSR-107)

          • 在內存中暫存 Java 對象的 API 和語義,包括對象的創建、共享訪問、緩存池、失效,以及跨 JVM 的一致性。

          Java State Management(JSR-350)

          • 應用程序和 Java EE 容器可使用該 API 將狀態管理的任務交給具有不同 QoS 特征的第三方提供者。
          • 基于 Java SE 的調用者可通過查詢狀態提供者來訪問狀態數據。
          • 可添加具有不同 QoS 的提供者,API 調用者能夠按自己的規則進行查詢。

          Batch Applications for the Java Platform(JSR-352)

          • 用于批處理應用程序的編程模型,以及用于調度和執行工作的運行時。
          • 為標準編程模型定義批處理工作、批處理工作步驟、批處理應用程序、批處理執行器和批處理工作管理器。

          Concurrency Utilities for Java EE(JSR-236)

          • 提供一個整潔、簡單且獨立的 API,使其能用于任何 Java EE 容器中。

          Java API for JSON Processing(JSR-353)

          • 處理 JSON 的 Java API。

          posted @ 2012-02-13 22:23 蜀山兆孨龘 閱讀(5768) | 評論 (0)編輯 收藏

          ForkJoinPool 是 Java SE 7 新功能“分叉/結合框架”的核心類,現在可能乏人問津,但我覺得它遲早會成為主流。分叉/結合框架是一個比較特殊的線程池框架,專用于需要將一個任務不斷分解成子任務(分叉),再不斷進行匯總得到最終結果(結合)的計算過程。比起傳統的線程池類 ThreadPoolExecutorForkJoinPool 實現了工作竊取算法,使得空閑線程能夠主動分擔從別的線程分解出來的子任務,從而讓所有的線程都盡可能處于飽滿的工作狀態,提高執行效率。

          ForkJoinPool 提供了三類方法來調度子任務:

          execute 系列
          異步執行指定的任務。
          invokeinvokeAll
          執行指定的任務,等待完成,返回結果。
          submit 系列
          異步執行指定的任務并立即返回一個 Future 對象。

          子任務由 ForkJoinTask 的實例來代表。它是一個抽象類,JDK 為我們提供了兩個實現:RecursiveTaskRecursiveAction,分別用于需要和不需要返回計算結果的子任務。ForkJoinTask 提供了三個靜態的 invokeAll 方法來調度子任務,注意只能在 ForkJoinPool 執行計算的過程中調用它們。

          ForkJoinPoolForkJoinTask 還提供了很多讓人眼花繚亂的公共方法,其實它們大多數都是其內部實現去調用的,對于應用開發人員來說意義不大。

          下面以統計 D 盤文件個數為例。這實際上是對一個文件樹的遍歷,我們需要遞歸地統計每個目錄下的文件數量,最后匯總,非常適合用分叉/結合框架來處理:

          // 處理單個目錄的任務
          public class CountingTask extends RecursiveTask<Integer> {
              private Path dir;
          
              public CountingTask(Path dir) {
                  this.dir = dir;
              }
          
              @Override
              protected Integer compute() {
                  int count = 0;
                  List<CountingTask> subTasks = new ArrayList<>();
          
                  // 讀取目錄 dir 的子路徑。
                  try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) {
                      for (Path subPath : ds) {
                          if (Files.isDirectory(subPath, LinkOption.NOFOLLOW_LINKS)) {
                              // 對每個子目錄都新建一個子任務。
                              subTasks.add(new CountingTask(subPath));
                          } else {
                              // 遇到文件,則計數器增加 1。
                              count++;
                          }
                      }
          
                      if (!subTasks.isEmpty()) {
                          // 在當前的 ForkJoinPool 上調度所有的子任務。
                          for (CountingTask subTask : invokeAll(subTasks)) {
                              count += subTask.join();
                          }
                      }
                  } catch (IOException ex) {
                      return 0;
                  }
                  return count;
              }
          }
          
          // 用一個 ForkJoinPool 實例調度“總任務”,然后敬請期待結果……
          Integer count = new ForkJoinPool().invoke(new CountingTask(Paths.get("D:/")));
              

          在我的筆記本上,經多次運行這段代碼,耗費的時間穩定在 600 豪秒左右。普通線程池(Executors.newCachedThreadPool())耗時 1100 毫秒左右,足見工作竊取的優勢。

          結束本文前,我們來圍觀一個最神奇的結果:單線程算法(使用 Files.walkFileTree(...))比這兩個都快,平均耗時 550 毫秒!這警告我們并非引入多線程就能優化性能,并須要先經過多次測試才能下結論。

          posted @ 2012-02-09 10:40 蜀山兆孨龘 閱讀(2694) | 評論 (2)編輯 收藏

          主站蜘蛛池模板: 通州区| 姜堰市| 上林县| 泸水县| 青神县| 长武县| 铜鼓县| 理塘县| 嘉义县| 香港 | 佛学| 五指山市| 东港市| 颍上县| 开化县| 乌兰察布市| 嵊州市| 固镇县| 洮南市| 锦屏县| 翁源县| 龙井市| 右玉县| 子洲县| 萍乡市| 莎车县| 沈丘县| 新宾| 廉江市| 西贡区| 应城市| 伊吾县| 巴彦县| 东源县| 宕昌县| 图们市| 会昌县| 浮梁县| 平阳县| 遂溪县| 正阳县|