Java學習

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

           

          多線程實現方式---實現Runnable接口

          多線程實現方式---實現Runnable接口

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

                   使用實現Runnable接口實現多線程的示例代碼如下:

                             /**

           * 測試類

           */

          public class Test2 {

                   public static void main(String[] args) {

                             //創建對象

                             MyRunnable mr = new MyRunnable();

                             Thread t = new Thread(mr);

                             //啟動

                             t.start();

                             try{

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

                                               Thread.sleep(1000);

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

                                      }

                             }catch(Exception e){}

                   }

          }

                   /**

           * 使用實現Runnable接口的方式實現多線程

           */

          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){}

                   }

          }

          該示例代碼實現的功能和前面實現的功能相同。在使用該方式實現時,使需要實現多線程的類實現Runnable,實現該接口需要覆蓋run方法,然后將需要以多線程方式執行的代碼書寫在run方法內部或在run方法內部進行調用。

          在需要啟動線程的地方,首先創建MyRunnable類型的對象,然后再以該對象為基礎創建Thread類的對象,最后調用Thread對象的start方法即可啟動線程。代碼如下:

          //創建對象

          MyRunnable mr = new MyRunnable();

          Thread t = new Thread(mr);

          //啟動

                   t.start();

          在這種實現方式中,大部分和前面介紹的方式類似,啟動的代碼稍微麻煩一些。這種方式也是實現線程的一種主要方式。

          12.2.3使用TimerTimerTask組合

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

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

                   在這種實現方式中,通過繼承TimerTask使該類獲得多線程的能力,將需要多線程執行的代碼書寫在run方法內部,然后通過Timer類啟動線程的執行。

                   在實際使用時,一個Timer可以啟動任意多個TimerTask實現的線程,但是多個線程之間會存在阻塞。所以如果多個線程之間如果需要完全獨立運行的話,最好還是一個Timer啟動一個TimerTask實現。

                   使用該種實現方式實現的多線程示例代碼如下:

                             import java.util.*;

          /**

           * 測試類

           */

          public class Test3 {

                   public static void main(String[] args) {

                             //創建Timer

                             Timer t = new Timer();

                             //創建TimerTask

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

                             //啟動線程

                             t.schedule(mtt1, 0);

                   }

          }

                            import java.util.TimerTask;

          /**

           * 以繼承TimerTask類的方式實現多線程

           */

          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類實現了多線程,以多線程方式執行的代碼書寫在該類的run方法內部,該類的功能和前面的多線程的代碼實現類似。

                   而在該代碼中,啟動線程時需要首先創建一個Timer類的對象,以及一個MyTimerTask線程類的兌現,然后使用Timer對象的schedule方法實現,啟動線程的代碼為:

          //創建Timer

          Timer t = new Timer();

          //創建TimerTask

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

          //啟動線程

                             t.schedule(mtt1, 0);

                   其中schedule方法中的第一個參數mtt1代表需要啟動的線程對象,而第二個參數0則代表延遲0毫秒啟動該線程,也就是立刻啟動。

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

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

          該方法的作用是在到達time指定的時間或已經超過該時間時執行線程task。例如假設tTimer對象,task是需要啟動的TimerTask線程對象,后續示例也采用這種約定實現,則啟動線程的示例代碼如下:

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

                     t. schedule(task,d);

          則該示例代碼的作用是在時間達到d指定的時間或超過該時間(例如2009102)時,啟動線程task

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

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

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

                     t. schedule(task,d,20000);

          該示例代碼的作用是當時間達到或超過d指定的時間以后,每隔20000毫秒就啟動一次線程task,這種方式會重復觸發線程。

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

          該方法和第一個方法類似,作用是在執行schedule方法以后delay毫秒以后啟動線程task。示例代碼如下:

                     t. schedule(task,1000);

          該示例代碼的作用是在執行該行啟動代碼1000毫秒以后啟動一次線程task

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

          該方法和第二個方法類似,作用是在執行schedule方法以后delay毫秒以后啟動線程task,然后每隔period毫秒重復啟動線程task

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

                   介紹完了schedule方法以后,讓我們再來看一下前面的示例代碼,如果在測試類中啟動兩個MyTimerTask線程,一種實現的代碼為:

                             import java.util.Timer;

          /**

           * 測試類

           */

          public class Test4 {

                   public static void main(String[] args) {

                             //創建Timer

                             Timer t = new Timer();

                             //創建TimerTask

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

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

                             //啟動線程

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

                             t.schedule(mtt1, 1000);

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

                             t.schedule(mtt2, 1000);

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

                   }

          }

                   在該示例代碼中,使用一個Timer對象t依次啟動了兩個MyTimerTask類型的對象mtt1mtt2。而程序的執行結果是:

                            開始啟動

          啟動線程1

          啟動線程2

          線程10

          線程11

          線程12

          線程13

          線程14

          線程15

          線程16

          線程17

          線程18

          線程19

          線程20

          線程21

          線程22

          線程23

          線程24

          線程25

          線程26

          線程27

          線程28

          線程29

                   從程序的執行結果可以看出,在Test4類中mtt1mtt2都被啟動,按照前面的schedule方法介紹,這兩個線程均會在線程啟動以后1000毫秒后獲得執行。但是從實際執行效果卻可以看出這兩個線程不是同時執行的,而是依次執行,這主要是因為一個Timer啟動的多個TimerTask之間會存在影響,當上一個線程未執行完成時,會阻塞后續線程的執行,所以當線程1執行完成以后線程2才獲得了執行。

                   如果需要線程1和線程2獲得同時執行,則只需要分別使用兩個Timer啟動TimerTask線程即可,啟動的示例代碼如下:

                             import java.util.Timer;

          /**

           * 測試類

           */

          public class Test5 {

                   public static void main(String[] args) {

                             //創建Timer

                             Timer t1 = new Timer();

                             Timer t2 = new Timer();

                             //創建TimerTask

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

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

                             //啟動線程

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

                             t1.schedule(mtt1, 1000);

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

                             t2.schedule(mtt2, 1000);

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

                   }

          }

                   在該示例中,分別使用兩個Timer對象t1t2,啟動兩個TimerTask線程對象mtt1mtt2,兩者之間不互相干擾,所以達到了同時執行的目的。

                   在使用上面的示例進行運行時,由于Timer自身的線程沒有結束,所以在程序輸出完成以后程序還沒有結束,需要手動結束程序的執行。例如在Eclipse中可以點擊控制臺上面的紅色“Teminate”按鈕結束程序。

          12.2.4 小結

                   關于線程的三種實現方式,就簡單的介紹這么多。其實無論那種實現方式,都可以實現多線程,在語法允許的前提下,可以使用任何一種方式實現。比較而言,實現Runnable接口方式要通用一些。

                   只是從語法角度介紹線程的實現方式,還是無法體會到線程實現的奧妙,下面將通過幾個簡單的示例來體會線程功能的強大,并體會并發編程的神奇,從而能夠進入并發編程的領域發揮技術的優勢。

          posted on 2009-06-15 13:21 找個美女做老婆 閱讀(35273) 評論(1)  編輯  收藏

          評論

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

          第三大師傅說師弟  回復  更多評論   


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


          網站導航:
           

          導航

          統計

          公告

          本blog已經搬到新家了, 新家:www.javaly.cn
           http://www.javaly.cn

          常用鏈接

          留言簿(6)

          隨筆檔案

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 岳阳县| 石阡县| 南康市| 江油市| 潞西市| 石门县| 桦南县| 庄河市| 思茅市| 白城市| 禹城市| 汉沽区| 五河县| 锡林郭勒盟| 东乡| 灵石县| 漳浦县| 汤原县| 怀宁县| 泰顺县| 北票市| 霍邱县| 无极县| 泽普县| 儋州市| 丹江口市| 上蔡县| 乐平市| 育儿| 冕宁县| 九江市| 集贤县| 黄大仙区| 惠州市| 扶余县| 大埔县| 周至县| 南汇区| 广水市| 渭源县| 内丘县|