新的起點 新的開始

          快樂生活 !

          (轉)Java 5.0多線程編程(2)

          *1: 定義了幾個任務

          *2: 初始了任務執行工具。任務的執行框架將會在后面解釋。

          *3: 執行任務,任務啟動時返回了一個 Future 對象,如果想得到任務執行的結果或者是異常可對這個 Future 對象進行操作。 Future 所含的值必須跟 Callable 所含的值對映,比如說例子中 Future 對印 Callable

          *4: 任務 1 正常執行完畢, future1.get() 會返回線程的值

          *5: 任務 2 在進行一個死循環,調用 future2.cancel(true) 來中止此線程。傳入的參數標明是否可打斷線程, true 表明可以打斷。

          *6: 任務 3 拋出異常,調用 future3.get() 時會引起異常的拋出。

          ? 運行 Executor 會有以下運行結果:

          looping....

          Task done. //*1

          looping....

          looping....//*2

          looping....

          looping....

          looping....

          looping....

          Thread 2 terminated? :true //*3

          //*4

          java.util.concurrent.ExecutionException: java.lang.Exception: Callable terminated with Exception!

          ??????? at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:205)

          ??????? at java.util.concurrent.FutureTask.get(FutureTask.java:80)

          ??????? at concurrent.Executor.main(Executor.java:43)

          ??????? …….

          *1: 任務 1 正常結束

          *2: 任務 2 是個死循環,這是它的打印結果

          *3: 指示任務 2 被取消

          *4: 在執行 future3.get() 時得到任務 3 拋出的異常

          3:新的任務執行架構

          ?? 在 Java 5.0 之前啟動一個任務是通過調用 Thread 類的 start() 方法來實現的,任務的提于交和執行是同時進行的,如果你想對任務的執行進行調度或是控制同時執行的線程數量就需要額外編寫代碼來完成。 5.0 里提供了一個新的任務執行架構使你可以輕松地調度和控制任務的執行,并且可以建立一個類似數據庫連接池的線程池來執行任務。這個架構主要有三個接口和其相應的具體類組成。這三個接口是 Executor, ExecutorService ScheduledExecutorService ,讓我們先用一個圖來顯示它們的關系:

          ?

          ? 圖的左側是接口,圖的右側是這些接口的具體類。注意 Executor 是沒有直接具體實現的。

          Executor 接口:

          是用來執行 Runnable 任務的,它只定義一個方法:

          • execute(Runnable command) :執行 Ruannable 類型的任務

          ExecutorService 接口:

          ExecutorService 繼承了 Executor 的方法,并提供了執行 Callable 任務和中止任務執行的服務,其定義的方法主要有:

          • submit(task) :可用來提交 Callable Runnable 任務,并返回代表此任務的 Future 對象
          • invokeAll(collection of tasks) :批處理任務集合,并返回一個代表這些任務的 Future 對象集合
          • shutdown() :在完成已提交的任務后關閉服務,不再接受新任務
          • shutdownNow() :停止所有正在執行的任務并關閉服務。
          • isTerminated() :測試是否所有任務都執行完畢了。
          • isShutdown() :測試是否該 ExecutorService 已被關閉

          ScheduledExecutorService 接口

          ExecutorService 的基礎上, ScheduledExecutorService 提供了按時間安排執行任務的功能,它提供的方法主要有:

          • schedule(task, initDelay): 安排所提交的 Callable Runnable 任務在 initDelay 指定的時間后執行。
          • scheduleAtFixedRate() :安排所提交的 Runnable 任務按指定的間隔重復執行
          • scheduleWithFixedDelay() :安排所提交的 Runnable 任務在每次執行完后,等待 delay 所指定的時間后重復執行。

          代碼: ScheduleExecutorService 的例子

          public class ScheduledExecutorServiceTest {

          ??????? public static void main(String[] args)

          ?????????????? throws InterruptedException, ExecutionException{

          ?????????????? //*1

          ??????????????? ScheduledExecutorService service = Executors.newScheduledThreadPool(2);

          ??????????????? //*2

          ??????????????? Runnable task1 = new Runnable() {

          ???????????????????? public void run() {

          ??????????????????????? System.out.println("Task repeating.");

          ???????????????????? }

          ??????????????? };

          ??????????????? //*3

          ??????????????? final ScheduledFuture future1 =

          ??????????????????????? service.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);

          ??????????????? //*4

          ??????????????? ScheduledFuture future2 = service.schedule(new Callable(){

          ???????????????????? public String call(){

          ???????????????????????????? future1.cancel(true);

          ???????????????????????????? return "task cancelled!";

          ??????????????? ?????}

          ??????????????? }, 5, TimeUnit.SECONDS);

          ??????????????? System.out.println(future2.get());

          //*5

          service.shutdown();

          ??????? }

          }

          ?? 這個例子有兩個任務,第一個任務每隔一秒打印一句“ Task repeating , 第二個任務在 5 秒鐘后取消第一個任務。

          *1: 初始化一個 ScheduledExecutorService 對象,這個對象的線程池大小為 2

          *2: 用內函數的方式定義了一個 Runnable 任務。

          *3: 調用所定義的 ScheduledExecutorService 對象來執行任務,任務每秒執行一次。能重復執行的任務一定是 Runnable 類型。注意我們可以用 TimeUnit 來制定時間單位,這也是 Java 5.0 里新的特征, 5.0 以前的記時單位是微秒,現在可精確到奈秒。

          *4: 調用 ScheduledExecutorService 對象來執行第二個任務,第二個任務所作的就是在 5 秒鐘后取消第一個任務。

          *5: 關閉服務。

          Executors

          ?? 雖然以上提到的接口有其實現的具體類,但為了方便 Java 5.0 建議使用 Executors 的工具類來得到 Executor 接口的具體對象,需要注意的是 Executors 是一個類,不是 Executor 的復數形式。 Executors 提供了以下一些 static 的方法:

          • callable(Runnable task): Runnable 的任務轉化成 Callable 的任務
          • newSingleThreadExecutor: 產生一個 ExecutorService 對象,這個對象只有一個線程可用來執行任務,若任務多于一個,任務將按先后順序執行。
          • newCachedThreadPool(): 產生一個 ExecutorService 對象,這個對象帶有一個線程池,線程池的大小會根據需要調整,線程執行完任務后返回線程池,供執行下一次任務使用。
          • newFixedThreadPool(int poolSize) :產生一個 ExecutorService 對象,這個對象帶有一個大小為 poolSize 的線程池,若任務數量大于 poolSize ,任務會被放在一個 queue 里順序執行。
          • newSingleThreadScheduledExecutor :產生一個 ScheduledExecutorService 對象,這個對象的線程池大小為 1 ,若任務多于一個,任務將按先后順序執行。
          • newScheduledThreadPool(int poolSize): 產生一個 ScheduledExecutorService 對象,這個對象的線程池大小為 poolSize ,若任務數量大于 poolSize ,任務會在一個 queue 里等待執行

          以下是得到和使用 ExecutorService 的例子:

          代碼:如何調用 Executors 來獲得各種服務對象

          //Single Threaded ExecutorService

          ???? ExecutorService singleThreadeService = Executors.newSingleThreadExecutor();

          //Cached ExecutorService

          ???? ExecutorService cachedService = Executors.newCachedThreadPool();

          //Fixed number of ExecutorService

          ???? ExecutorService fixedService = Executors.newFixedThreadPool(3);

          //Single ScheduledExecutorService

          ???? ScheduledExecutorService singleScheduledService =

          ????????? Executors.newSingleThreadScheduledExecutor();

          //Fixed number of ScheduledExecutorService

          ScheduledExecutorService fixedScheduledService =

          ???? Executors.newScheduledThreadPool(3);

          4LockersCondition接口

          ?? 在多線程編程里面一個重要的概念是鎖定,如果一個資源是多個線程共享的,為了保證數據的完整性,在進行事務性操作時需要將共享資源鎖定,這樣可以保證在做事務性操作時只有一個線程能對資源進行操作,從而保證數據的完整性。在 5.0 以前,鎖定的功能是由 Synchronized 關鍵字來實現的,這樣做存在幾個問題:

          • 每次只能對一個對象進行鎖定。若需要鎖定多個對象,編程就比較麻煩,一不小心就會出現死鎖現象。
          • 如果線程因拿不到鎖定而進入等待狀況,是沒有辦法將其打斷的

          Java 5.0 里出現兩種鎖的工具可供使用,下圖是這兩個工具的接口及其實現:

          posted on 2007-03-26 14:30 advincenting 閱讀(470) 評論(0)  編輯  收藏


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


          網站導航:
           

          公告

          Locations of visitors to this pageBlogJava
        1. 首頁
        2. 新隨筆
        3. 聯系
        4. 聚合
        5. 管理
        6. <2007年3月>
          25262728123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          統計

          常用鏈接

          留言簿(13)

          隨筆分類(71)

          隨筆檔案(179)

          文章檔案(13)

          新聞分類

          IT人的英語學習網站

          JAVA站點

          優秀個人博客鏈接

          官網學習站點

          生活工作站點

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 饶河县| 措美县| 岑溪市| 贺兰县| 大洼县| 柯坪县| 万载县| 木里| 扶沟县| 兴宁市| 钟山县| 黄大仙区| 林口县| 余干县| 五莲县| 双流县| 越西县| 德江县| 成都市| 泰安市| 大石桥市| 乌兰浩特市| 通渭县| 荥经县| 固始县| 辽宁省| 龙川县| 临潭县| 民权县| 大理市| 逊克县| 昭苏县| 建昌县| 娄底市| 敦煌市| 司法| 克东县| 梧州市| 孟津县| 淮阳县| 宿州市|