新的起點(diǎn) 新的開始

          快樂(lè)生活 !

          (轉(zhuǎn))Java 5.0多線程編程(1)

          最近看了幾個(gè)多線程設(shè)計(jì)模式,對(duì)照J(rèn)2SE5.0里的多線程工具,兩者很相似。從網(wǎng)上找了幾篇J2SE5.0多線程工具例子, 供參考

          (轉(zhuǎn)自賽迪網(wǎng))

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

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

          2.????? 如果使用不當(dāng),會(huì)使程序的運(yùn)行效率大大降低。

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

          4.????? 因?yàn)殒i定的功能是通過(guò) Synchronized 來(lái)實(shí)現(xiàn)的,這是一種塊結(jié)構(gòu),只能對(duì)代碼中的一段代碼進(jìn)行鎖定,而且鎖定是單一的。如以下代碼所示:

          synchronized lock {

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

          ??? ……

          }

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

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

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

          public class ServerThread {

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

          ????? int count = 2;

          public void runTwoThreads() {

          ????? // 啟動(dòng)兩個(gè)線程去初始化組件

          ??????????? 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:三個(gè)新加的多線程包

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

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

          2Callable Future接口

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

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

          以下是 Callable 的一個(gè)例子:

          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 類實(shí)現(xiàn)了 Callable String 將是 call 方法的返回值類型。例子中用了 String ,但可以是任何 Java 類。

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

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

          以下是調(diào)用 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 閱讀(399) 評(píng)論(0)  編輯  收藏


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


          網(wǎng)站導(dǎo)航:
           

          公告

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

          統(tǒng)計(jì)

          常用鏈接

          留言簿(13)

          隨筆分類(71)

          隨筆檔案(179)

          文章檔案(13)

          新聞分類

          IT人的英語(yǔ)學(xué)習(xí)網(wǎng)站

          JAVA站點(diǎn)

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

          官網(wǎng)學(xué)習(xí)站點(diǎn)

          生活工作站點(diǎn)

          最新隨筆

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 安多县| 囊谦县| 上栗县| 汶川县| 辽中县| 清苑县| 雅安市| 衡山县| 武山县| 营山县| 通河县| 济源市| 菏泽市| 安阳市| 卓资县| 修水县| 天全县| 桑植县| 台中市| 佛学| 鄂尔多斯市| 敦煌市| 和平区| 青铜峡市| 应用必备| 张家界市| 台湾省| 麻江县| 东明县| 汾西县| 仁寿县| 克拉玛依市| 西城区| 河南省| 拜城县| 土默特右旗| 嵩明县| 泾阳县| 山东省| 越西县| 梅河口市|