新的起點 新的開始

          快樂生活 !

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

          最近看了幾個多線程設計模式,對照J2SE5.0里的多線程工具,兩者很相似。從網上找了幾篇J2SE5.0多線程工具例子, 供參考

          (轉自賽迪網)

          Java1995年面世以來得到了廣泛得一個運用,但是對多線程編程的支持Java很長時間一直停留在初級階段。在Java 5.0之前Java里的多線程編程主要是通過Thread類,Runnable接口,Object對象中的wait() notify() notifyAll()等方法和synchronized關鍵詞來實現(xiàn)的。這些工具雖然能在大多數(shù)情況下解決對共享資源的管理和線程間的調度,但存在以下幾個問題

          1.????? 過于原始,拿來就能用的功能有限,即使是要實現(xiàn)簡單的多線程功能也需要編寫大量的代碼。這些工具就像匯編語言一樣難以學習和使用,比這更糟糕的是稍有不慎它們還可能被錯誤地使用,而且這樣的錯誤很難被發(fā)現(xiàn)。

          2.????? 如果使用不當,會使程序的運行效率大大降低。

          3.????? 為了提高開發(fā)效率,簡化編程,開發(fā)人員在做項目的時候往往需要寫一些共享的工具來實現(xiàn)一些普遍適用的功能。但因為沒有規(guī)范,相同的工具會被重復地開發(fā),造成資源浪費。

          4.????? 因為鎖定的功能是通過 Synchronized 來實現(xiàn)的,這是一種塊結構,只能對代碼中的一段代碼進行鎖定,而且鎖定是單一的。如以下代碼所示:

          synchronized lock {

          ? ?? // 執(zhí)行對共享資源的操作

          ??? ……

          }

          ??? ? 一些復雜的功能就很難被實現(xiàn)。比如說如果程序需要取得 lock A lock B 來進行操作 1 ,然后需要取得 lock C 并且釋放 lock A 來進行操作 2 Java 5.0 之前的多線程框架就顯得無能為力了。

          ?? 因為這些問題,程序員對舊的框架一直頗有微詞。這種情況一直到 Java 5.0 才有較大的改觀,一系列的多線程工具包被納入了標準庫文件。這些工具包括了一個新的多線程程序的執(zhí)行框架,使編程人員可方便地協(xié)調和調度線程的運行,并且新加入了一些高性能的常用的工具,使程序更容易編寫,運行效率更高。本文將分類并結合例子來介紹這些新加的多線程工具。

          ?? 在我們開始介紹 Java 5.0 里的新 Concurrent 工具前讓我們先來看一下一個用舊的多線程工具編寫的程序,這個程序里有一個 Server 線程,它需要啟動兩個 Component Server 線程需等到 Component 線程完畢后再繼續(xù)。相同的功能在 Synchronizer 一章里用新加的工具 CountDownLatch 有相同的實現(xiàn)。兩個程序,孰優(yōu)孰劣,哪個程序更容易編寫,哪個程序更容易理解,相信大家看過之后不難得出結論。

          public class ServerThread {

          ????? Object concLock = new Object();

          ????? int count = 2;

          public void runTwoThreads() {

          ????? // 啟動兩個線程去初始化組件

          ??????????? new Thread(new ComponentThread1(this)).start();

          ??????????? new Thread(new ComponentThread1(this)).start();

          ??????????? // Wait for other thread

          while(count != 0) {

          ????????????????? synchronized(concLock) {

          ??????????????????????? try {

          ????????????????????????????? concLock.wait();

          ????????????????????????????? System.out.println("Wake up.");

          ??????????????????????? } catch (InterruptedException ie) { // 處理異常 }

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

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

          ??????????? System.out.println("Server is up.");

          ????? }

          ????? public void callBack() {

          synchronized(concLock) {

          ????????????????? count--;

          ????????????????? concLock.notifyAll();

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

          ????? }

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

          ??????????? ServerThread server = new ServerThread();

          ??????????? server.runTwoThreads();

          ????? }

          }

          ?

          public class ComponentThread1 implements Runnable {

          ????? private ServerThread server;

          ????? public ComponentThread1(ServerThread server) {

          ??????????? this.server = server;

          ????? }

          public void run() {

          ????? // 做組件初始化的工作

          ??????????? System.out.println("Do component initialization.");

          ??????????? server.callBack();

          ????? }

          }

          1:三個新加的多線程包

          ?? Java 5.0 里新加入了三個多線程包: java.util.concurrent, java.util.concurrent.atomic, java.util.concurrent.locks.

          • java.util.concurrent 包含了常用的多線程工具,是新的多線程工具的主體。
          • java.util.concurrent.atomic 包含了不用加鎖情況下就能改變值的原子變量,比如說 AtomicInteger 提供了 addAndGet() 方法。 Add Get 是兩個不同的操作,為了保證別的線程不干擾,以往的做法是先鎖定共享的變量,然后在鎖定的范圍內進行兩步操作。但用 AtomicInteger.addAndGet() 就不用擔心鎖定的事了,其內部實現(xiàn)保證了這兩步操作是在原子量級發(fā)生的,不會被別的線程干擾。
          • java.util.concurrent.locks 包包含鎖定的工具。

          2Callable Future接口

          ?? Callable 是類似于 Runnable 的接口,實現(xiàn) Callable 接口的類和實現(xiàn) Runnable 的類都是可被其它線程執(zhí)行的任務。 Callable Runnable 有幾點不同:

          • Callable 規(guī)定的方法是 call() ,而 Runnable 規(guī)定的方法是 run().
          • Callable 的任務執(zhí)行后可返回值,而 Runnable 的任務是不能返回值的。
          • call ()方法可拋出異常,而 run ()方法是不能拋出異常的。
          • 運行 Callable 任務可拿到一個 Future 對象,通過 Future 對象可了解任務執(zhí)行情況,可取消任務的執(zhí)行,還可獲取任務執(zhí)行的結果。

          以下是 Callable 的一個例子:

          public class DoCallStuff implements Callable{ // *1

          ??????? private int aInt;

          ??????? public DoCallStuff(int aInt) {

          ??????????????? this.aInt = aInt;

          ??????? }

          ??????? public String call() throws Exception { //*2

          ??????????????? boolean resultOk = false;

          ??????????????? if(aInt == 0){

          ??????????????????????? resultOk = true;

          ??????????????? }? else if(aInt == 1){

          ??????????????????????? while(true){ //infinite loop

          ?????????????????? ?????????????System.out.println("looping....");

          ??????????????????????????????? Thread.sleep(3000);

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

          ??????????????? } else {

          ??????????????????????? throw new Exception("Callable terminated with Exception!"); //*3

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

          ??????????????? if(resultOk){

          ??????????????????????? return "Task done.";

          ??????????????? } else {

          ??????????????????????? return "Task failed";

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

          ??????? }

          }

          *1: 名為 DoCallStuff 類實現(xiàn)了 Callable String 將是 call 方法的返回值類型。例子中用了 String ,但可以是任何 Java 類。

          *2: call 方法的返回值類型為 String ,這是和類的定義相對應的。并且可以拋出異常。

          *3: call 方法可以拋出異常,如加重的斜體字所示。

          以下是調用 DoCallStuff 的主程序。

          import java.util.concurrent.ExecutionException;

          import java.util.concurrent.ExecutorService;

          import java.util.concurrent.Executors;

          import java.util.concurrent.Future;

          public class Executor {

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

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

          ??????????????? DoCallStuff call1 = new DoCallStuff(0);

          ??????????????? DoCallStuff call2 = new DoCallStuff(1);

          ??????????????? DoCallStuff call3 = new DoCallStuff(2);

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

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

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

          ??????????????? Future future1 = es.submit(call1);

          ??????????????? Future future2 = es.submit(call2);

          ???? ???????????Future future3 = es.submit(call3);

          ??????????????? try {

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

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

          ???????????????????????? //*5

          ??????????????????????? Thread.sleep(3000);

          ????????????????? ??????System.out.println("Thread 2 terminated? :" + future2.cancel(true));

          ??????????????????????? //*6

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

          ??????????????? } catch (ExecutionException ex) {

          ??????????????????????? ex.printStackTrace();

          ??????????????? } catch (InterruptedException ex) {

          ??????????????????????? ex.printStackTrace();

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

          ??????? }

          }

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


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


          網站導航:
           

          公告

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

          統(tǒng)計

          常用鏈接

          留言簿(13)

          隨筆分類(71)

          隨筆檔案(179)

          文章檔案(13)

          新聞分類

          IT人的英語學習網站

          JAVA站點

          優(yōu)秀個人博客鏈接

          官網學習站點

          生活工作站點

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 长汀县| 三穗县| 怀宁县| 福泉市| 鹤峰县| 温宿县| 荔波县| 微山县| 安陆市| 辰溪县| 义乌市| 金湖县| 和林格尔县| 太湖县| 沁水县| 绥德县| 安岳县| 扬州市| 花莲市| 恩平市| 隆化县| 南充市| 宽甸| 连平县| 习水县| 临猗县| 古田县| 白朗县| 永昌县| 福安市| 射阳县| 磐安县| 乌拉特中旗| 安庆市| 巴彦县| 潜山县| 江城| 双流县| 淅川县| 溧阳市| 正镶白旗|