Java學(xué)習(xí)

          java,spring,structs,hibernate,jsf,ireport,jfreechart,jasperreport,tomcat,jboss -----本博客已經(jīng)搬家了,新的地址是 http://www.javaly.cn 如果有對(duì)文章有任何疑問或者有任何不懂的地方,歡迎到www.javaly.cn (Java樂園)指出,我會(huì)盡力幫助解決。一起進(jìn)步

           

          多線程實(shí)現(xiàn)方式---實(shí)現(xiàn)Runnable接口

          多線程實(shí)現(xiàn)方式---實(shí)現(xiàn)Runnable接口

          一個(gè)類如果需要具備多線程的能力,也可以通過實(shí)現(xiàn)
          java.lang.Runnable接口進(jìn)行實(shí)現(xiàn)。按照Java語(yǔ)言的語(yǔ)法,一個(gè)類可以實(shí)現(xiàn)任意多個(gè)接口,所以該種實(shí)現(xiàn)方式在實(shí)際實(shí)現(xiàn)時(shí)的通用性要比前面介紹的方式好一些。

                   使用實(shí)現(xiàn)Runnable接口實(shí)現(xiàn)多線程的示例代碼如下:

                             /**

           * 測(cè)試類

           */

          public class Test2 {

                   public static void main(String[] args) {

                             //創(chuàng)建對(duì)象

                             MyRunnable mr = new MyRunnable();

                             Thread t = new Thread(mr);

                             //啟動(dòng)

                             t.start();

                             try{

                                      for(int i = 0;i < 10;i++){

                                               Thread.sleep(1000);

                                               System.out.println("main:" + i);

                                      }

                             }catch(Exception e){}

                   }

          }

                   /**

           * 使用實(shí)現(xiàn)Runnable接口的方式實(shí)現(xiàn)多線程

           */

          public class MyRunnable implements Runnable {

                   public void run() {

                             try{

                                      for(int i = 0;i < 10;i++){

                                               Thread.sleep(1000);

                                               System.out.println("run:" + i);

                                      }

                             }catch(Exception e){}

                   }

          }

          該示例代碼實(shí)現(xiàn)的功能和前面實(shí)現(xiàn)的功能相同。在使用該方式實(shí)現(xiàn)時(shí),使需要實(shí)現(xiàn)多線程的類實(shí)現(xiàn)Runnable,實(shí)現(xiàn)該接口需要覆蓋run方法,然后將需要以多線程方式執(zhí)行的代碼書寫在run方法內(nèi)部或在run方法內(nèi)部進(jìn)行調(diào)用。

          在需要啟動(dòng)線程的地方,首先創(chuàng)建MyRunnable類型的對(duì)象,然后再以該對(duì)象為基礎(chǔ)創(chuàng)建Thread類的對(duì)象,最后調(diào)用Thread對(duì)象的start方法即可啟動(dòng)線程。代碼如下:

          //創(chuàng)建對(duì)象

          MyRunnable mr = new MyRunnable();

          Thread t = new Thread(mr);

          //啟動(dòng)

                   t.start();

          在這種實(shí)現(xiàn)方式中,大部分和前面介紹的方式類似,啟動(dòng)的代碼稍微麻煩一些。這種方式也是實(shí)現(xiàn)線程的一種主要方式。

          12.2.3使用TimerTimerTask組合

                   最后一種實(shí)現(xiàn)多線程的方式,就是使用java.util包中的TimerTimerTask類實(shí)現(xiàn)多線程,使用這種方式也可以比較方便的實(shí)現(xiàn)線程。

                   在這種實(shí)現(xiàn)方式中,Timer類實(shí)現(xiàn)的是類似鬧鐘的功能,也就是定時(shí)或者每隔一定時(shí)間觸發(fā)一次線程。其實(shí),Timer類本身實(shí)現(xiàn)的就是一個(gè)線程,只是這個(gè)線程是用來實(shí)現(xiàn)調(diào)用其它線程的。而TimerTask類是一個(gè)抽象類,該類實(shí)現(xiàn)了Runnable接口,所以按照前面的介紹,該類具備多線程的能力。

                   在這種實(shí)現(xiàn)方式中,通過繼承TimerTask使該類獲得多線程的能力,將需要多線程執(zhí)行的代碼書寫在run方法內(nèi)部,然后通過Timer類啟動(dòng)線程的執(zhí)行。

                   在實(shí)際使用時(shí),一個(gè)Timer可以啟動(dòng)任意多個(gè)TimerTask實(shí)現(xiàn)的線程,但是多個(gè)線程之間會(huì)存在阻塞。所以如果多個(gè)線程之間如果需要完全獨(dú)立運(yùn)行的話,最好還是一個(gè)Timer啟動(dòng)一個(gè)TimerTask實(shí)現(xiàn)。

                   使用該種實(shí)現(xiàn)方式實(shí)現(xiàn)的多線程示例代碼如下:

                             import java.util.*;

          /**

           * 測(cè)試類

           */

          public class Test3 {

                   public static void main(String[] args) {

                             //創(chuàng)建Timer

                             Timer t = new Timer();

                             //創(chuàng)建TimerTask

                             MyTimerTask mtt1 = new MyTimerTask("線程1");

                             //啟動(dòng)線程

                             t.schedule(mtt1, 0);

                   }

          }

                            import java.util.TimerTask;

          /**

           * 以繼承TimerTask類的方式實(shí)現(xiàn)多線程

           */

          public class MyTimerTask extends TimerTask {

                   String s;

                   public MyTimerTask(String s){

                             this.s = s;

                   }

                  

                   public void run() {

                             try{

                                      for(int i = 0;i < 10;i++){

                                               Thread.sleep(1000);

                                               System.out.println(s + i);

                                      }

                             }catch(Exception e){}

                   }

          }

                   在該示例中,MyTimerTask類實(shí)現(xiàn)了多線程,以多線程方式執(zhí)行的代碼書寫在該類的run方法內(nèi)部,該類的功能和前面的多線程的代碼實(shí)現(xiàn)類似。

                   而在該代碼中,啟動(dòng)線程時(shí)需要首先創(chuàng)建一個(gè)Timer類的對(duì)象,以及一個(gè)MyTimerTask線程類的兌現(xiàn),然后使用Timer對(duì)象的schedule方法實(shí)現(xiàn),啟動(dòng)線程的代碼為:

          //創(chuàng)建Timer

          Timer t = new Timer();

          //創(chuàng)建TimerTask

          MyTimerTask mtt1 = new MyTimerTask("線程1");

          //啟動(dòng)線程

                             t.schedule(mtt1, 0);

                   其中schedule方法中的第一個(gè)參數(shù)mtt1代表需要啟動(dòng)的線程對(duì)象,而第二個(gè)參數(shù)0則代表延遲0毫秒啟動(dòng)該線程,也就是立刻啟動(dòng)。

                   由于schedule方法比較重要,下面詳細(xì)介紹一下Timer類中的四個(gè)schedule方法:

          1、 public void schedule(TimerTask task,Date time)

          該方法的作用是在到達(dá)time指定的時(shí)間或已經(jīng)超過該時(shí)間時(shí)執(zhí)行線程task。例如假設(shè)tTimer對(duì)象,task是需要啟動(dòng)的TimerTask線程對(duì)象,后續(xù)示例也采用這種約定實(shí)現(xiàn),則啟動(dòng)線程的示例代碼如下:

                   Date d = new Date(2009-1900,10-1,1,10,0,0);

                     t. schedule(task,d);

          則該示例代碼的作用是在時(shí)間達(dá)到d指定的時(shí)間或超過該時(shí)間(例如2009102號(hào))時(shí),啟動(dòng)線程task

          2、 public void schedule(TimerTask task, Date firstTime, long period)

          該方法的作用是在時(shí)間到達(dá)firstTime開始,每隔period毫秒就啟動(dòng)一次task指定的線程。示例代碼如下:

                     Date d = new Date(2009-1900,10-1,1,10,0,0);

                     t. schedule(task,d,20000);

          該示例代碼的作用是當(dāng)時(shí)間達(dá)到或超過d指定的時(shí)間以后,每隔20000毫秒就啟動(dòng)一次線程task,這種方式會(huì)重復(fù)觸發(fā)線程。

          3、 public void schedule(TimerTask task,long delay)

          該方法和第一個(gè)方法類似,作用是在執(zhí)行schedule方法以后delay毫秒以后啟動(dòng)線程task。示例代碼如下:

                     t. schedule(task,1000);

          該示例代碼的作用是在執(zhí)行該行啟動(dòng)代碼1000毫秒以后啟動(dòng)一次線程task

          4、 public void schedule(TimerTask task,long delay,long period)

          該方法和第二個(gè)方法類似,作用是在執(zhí)行schedule方法以后delay毫秒以后啟動(dòng)線程task,然后每隔period毫秒重復(fù)啟動(dòng)線程task

                   例外需要說明的是Timer類中啟動(dòng)線程還包含兩個(gè)scheduleAtFixedRate方法,這兩個(gè)方法的參數(shù)和上面的第二個(gè)和第四個(gè)一致,其作用是實(shí)現(xiàn)重復(fù)啟動(dòng)線程時(shí)的精確延時(shí)。對(duì)于schedule方法來說,如果重復(fù)的時(shí)間間隔是1000毫秒,則實(shí)際的延遲時(shí)間是1000毫秒加上系統(tǒng)執(zhí)行時(shí)消耗的時(shí)間,例如為5毫秒,則實(shí)際每輪的時(shí)間間隔為1005毫秒。而對(duì)于scheduleAtFixedRate方法來說,如果設(shè)置的重復(fù)時(shí)間間隔為1000毫秒,系統(tǒng)執(zhí)行時(shí)消耗的時(shí)間為5毫秒,則延遲時(shí)間就會(huì)變成995毫秒,從而保證每輪間隔為1000毫秒。

                   介紹完了schedule方法以后,讓我們?cè)賮砜匆幌虑懊娴氖纠a,如果在測(cè)試類中啟動(dòng)兩個(gè)MyTimerTask線程,一種實(shí)現(xiàn)的代碼為:

                             import java.util.Timer;

          /**

           * 測(cè)試類

           */

          public class Test4 {

                   public static void main(String[] args) {

                             //創(chuàng)建Timer

                             Timer t = new Timer();

                             //創(chuàng)建TimerTask

                             MyTimerTask mtt1 = new MyTimerTask("線程1");

                             MyTimerTask mtt2 = new MyTimerTask("線程2");

                             //啟動(dòng)線程

                             System.out.println("開始啟動(dòng)");

                             t.schedule(mtt1, 1000);

                             System.out.println("啟動(dòng)線程1");

                             t.schedule(mtt2, 1000);

                             System.out.println("啟動(dòng)線程2");

                   }

          }

                   在該示例代碼中,使用一個(gè)Timer對(duì)象t依次啟動(dòng)了兩個(gè)MyTimerTask類型的對(duì)象mtt1mtt2。而程序的執(zhí)行結(jié)果是:

                            開始啟動(dòng)

          啟動(dòng)線程1

          啟動(dòng)線程2

          線程10

          線程11

          線程12

          線程13

          線程14

          線程15

          線程16

          線程17

          線程18

          線程19

          線程20

          線程21

          線程22

          線程23

          線程24

          線程25

          線程26

          線程27

          線程28

          線程29

                   從程序的執(zhí)行結(jié)果可以看出,在Test4類中mtt1mtt2都被啟動(dòng),按照前面的schedule方法介紹,這兩個(gè)線程均會(huì)在線程啟動(dòng)以后1000毫秒后獲得執(zhí)行。但是從實(shí)際執(zhí)行效果卻可以看出這兩個(gè)線程不是同時(shí)執(zhí)行的,而是依次執(zhí)行,這主要是因?yàn)橐粋€(gè)Timer啟動(dòng)的多個(gè)TimerTask之間會(huì)存在影響,當(dāng)上一個(gè)線程未執(zhí)行完成時(shí),會(huì)阻塞后續(xù)線程的執(zhí)行,所以當(dāng)線程1執(zhí)行完成以后線程2才獲得了執(zhí)行。

                   如果需要線程1和線程2獲得同時(shí)執(zhí)行,則只需要分別使用兩個(gè)Timer啟動(dòng)TimerTask線程即可,啟動(dòng)的示例代碼如下:

                             import java.util.Timer;

          /**

           * 測(cè)試類

           */

          public class Test5 {

                   public static void main(String[] args) {

                             //創(chuàng)建Timer

                             Timer t1 = new Timer();

                             Timer t2 = new Timer();

                             //創(chuàng)建TimerTask

                             MyTimerTask mtt1 = new MyTimerTask("線程1");

                             MyTimerTask mtt2 = new MyTimerTask("線程2");

                             //啟動(dòng)線程

                             System.out.println("開始啟動(dòng)");

                             t1.schedule(mtt1, 1000);

                             System.out.println("啟動(dòng)線程1");

                             t2.schedule(mtt2, 1000);

                             System.out.println("啟動(dòng)線程2");

                   }

          }

                   在該示例中,分別使用兩個(gè)Timer對(duì)象t1t2,啟動(dòng)兩個(gè)TimerTask線程對(duì)象mtt1mtt2,兩者之間不互相干擾,所以達(dá)到了同時(shí)執(zhí)行的目的。

                   在使用上面的示例進(jìn)行運(yùn)行時(shí),由于Timer自身的線程沒有結(jié)束,所以在程序輸出完成以后程序還沒有結(jié)束,需要手動(dòng)結(jié)束程序的執(zhí)行。例如在Eclipse中可以點(diǎn)擊控制臺(tái)上面的紅色“Teminate”按鈕結(jié)束程序。

          12.2.4 小結(jié)

                   關(guān)于線程的三種實(shí)現(xiàn)方式,就簡(jiǎn)單的介紹這么多。其實(shí)無(wú)論那種實(shí)現(xiàn)方式,都可以實(shí)現(xiàn)多線程,在語(yǔ)法允許的前提下,可以使用任何一種方式實(shí)現(xiàn)。比較而言,實(shí)現(xiàn)Runnable接口方式要通用一些。

                   只是從語(yǔ)法角度介紹線程的實(shí)現(xiàn)方式,還是無(wú)法體會(huì)到線程實(shí)現(xiàn)的奧妙,下面將通過幾個(gè)簡(jiǎn)單的示例來體會(huì)線程功能的強(qiáng)大,并體會(huì)并發(fā)編程的神奇,從而能夠進(jìn)入并發(fā)編程的領(lǐng)域發(fā)揮技術(shù)的優(yōu)勢(shì)。

          posted on 2009-06-15 13:21 找個(gè)美女做老婆 閱讀(35285) 評(píng)論(1)  編輯  收藏

          評(píng)論

          # 多線程 2015-11-14 19:32

          第三大師傅說師弟  回復(fù)  更多評(píng)論   


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


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

          導(dǎo)航

          統(tǒng)計(jì)

          公告

          本blog已經(jīng)搬到新家了, 新家:www.javaly.cn
           http://www.javaly.cn

          常用鏈接

          留言簿(6)

          隨筆檔案

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 澎湖县| SHOW| 武安市| 隆子县| 江达县| 巴马| 台江县| 屏南县| 洛南县| 抚顺县| 大邑县| 高雄市| 徐汇区| 永康市| 罗山县| 九龙坡区| 佛坪县| 湟中县| 察哈| 尖扎县| 江油市| 余江县| 罗定市| 信阳市| 太仓市| 屏东市| 阳西县| 长治市| 城市| 谢通门县| 黄梅县| 河西区| 阳西县| 盐池县| 简阳市| 贵南县| 巢湖市| 张家港市| 奇台县| 奉新县| 探索|