如何創建并運行java線程

原文鏈接? 譯者:章筱虎 ?校對:方騰飛

Java線程類也是一個object類,它的實例都繼承自java.lang.Thread或其子類。?可以用如下方式用java中創建一個線程:

Tread thread = new Thread();

執行該線程可以調用該線程的start()方法:

thread.start();


在上面的例子中,我們并沒有為線程編寫運行代碼,因此調用該方法后線程就終止了。

編寫線程運行時執行的代碼有兩種方式:一種是創建Thread子類的一個實例并重寫run方法,第二種是創建類的時候實現Runnable接口。接下來我們會具體講解這兩種方法:

創建Thread的子類

創建Thread子類的一個實例并重寫run方法,run方法會在調用start()方法之后被執行。例子如下:

public class MyThread extends Thread {
   public void run(){
     System.out.println("MyThread running");
   }
}

可以用如下方式創建并運行上述Thread子類

MyThread myThread = new MyThread();
myTread.start();

一旦線程啟動后start方法就會立即返回,而不會等待到run方法執行完畢才返回。就好像run方法是在另外一個cpu上執行一樣。當run方法執行后,將會打印出字符串MyThread running。

你也可以如下創建一個Thread的匿名子類:

Thread thread = new Thread(){
   public void run(){
     System.out.println("Thread Running");
   }
};
thread.start();

當新的線程的run方法執行以后,計算機將會打印出字符串”Thread Running”。

實現Runnable接口

???????? 第二種編寫線程執行代碼的方式是新建一個實現了java.lang.Runnable接口的類的實例,實例中的方法可以被線程調用。下面給出例子:

public class MyRunnable implements Runnable {
   public void run(){
    System.out.println("MyRunnable running");
   }
}

為了使線程能夠執行run()方法,需要在Thread類的構造函數中傳入?MyRunnable的實例對象。示例如下:

Thread thread = new Thread(new MyRunnable());
thread.start();

???????? 當線程運行時,它將會調用實現了Runnable接口的run方法。上例中將會打印出”MyRunnable running”。

同樣,也可以創建一個實現了Runnable接口的匿名類,如下所示:

Runnable myRunnable = new Runnable(){
   public void run(){
     System.out.println("Runnable running");
   }
}
Thread thread = new Thread(myRunnable);
thread.start();

創建子類還是實現Runnable接口?

對于這兩種方式哪種好并沒有一個確定的答案,它們都能滿足要求。就我個人意見,我更傾向于實現Runnable接口這種方法。因為線程池可以有效的管理實現了Runnable接口的線程,如果線程池滿了,新的線程就會排隊等候執行,直到線程池空閑出來為止。而如果線程是通過實現Thread子類實現的,這將會復雜一些。

有時我們要同時融合實現Runnable接口和Thread子類兩種方式。例如,實現了Thread子類的實例可以執行多個實現了Runnable接口的線程。一個典型的應用就是線程池。

常見錯誤:調用run()方法而非start()方法

創建并運行一個線程所犯的常見錯誤是調用線程的run()方法而非start()方法,如下所示:

Thread newThread = new Thread(MyRunnable());
newThread.run();? //should be start();

起初你并不會感覺到有什么不妥,因為run()方法的確如你所愿的被調用了。但是,事實上,run()方法并非是由剛創建的新線程所執行的,而是被創建新線程的當前線程所執行了。也就是被執行上面兩行代碼的線程所執行的。想要讓創建的新線程執行run()方法,必須調用新線程的start方法。

線程名

當創建一個線程的時候,可以給線程起一個名字。它有助于我們區分不同的線程。例如:如果有多個線程寫入System.out,我們就能夠通過線程名容易的找出是哪個線程正在輸出。例子如下:

MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable, "New Thread");
thread.start();
System.out.println(thread.getName());

需要注意的是,因為MyRunnable并非Thread的子類,所以MyRunnable類并沒有getName()方法??梢酝ㄟ^以下方式得到當前線程的引用:

Thread.currentThread();

因此,通過如下代碼可以得到當前線程的名字:

 String threadName = Thread.currentThread().getName();

線程代碼舉例:
這里是一個小小的例子。首先輸出執行main()方法線程名字。這個線程JVM分配的。然后開啟10個線程,命名為1~10。每個線程輸出自己的名字后就退出。

public class ThreadExample {
  public static void main(String[] args){
     System.out.println(Thread.currentThread().getName());
      for(int i=0; i<10; i++){
         new Thread("" + i){
            public void run(){
             System.out.println("Thread: " + getName() + "running");
            }
         }.start();
      }
  }
}

需要注意的是,盡管啟動線程的順序是有序的,但是執行的順序并非是有序的。也就是說,1號線程并不一定是第一個將自己名字輸出到控制臺的線程。這是因為線程是并行執行而非順序的。Jvm和操作系統一起決定了線程的執行順序,他和線程的啟動順序并非一定是一致的。

原創文章,轉載請注明: 轉載自并發編程網 – www.okfdzs1908.com本文鏈接地址: 如何創建并運行java線程


FavoriteLoading添加本文到我的收藏
  • Trackback 關閉
  • 評論 (15)
    • Snway
    • 2013/03/24 10:45下午

    通俗易懂!

  1. 因為線程池可以有效的管理實現了Runnable接口的線程,如果線程池滿了,新的線程就會排隊等候執行,直到線程池空閑出來為止。而如果線程是通過實現Thread子類實現的,這將會復雜一些

    初學,這句話沒看懂,不知道為什么,求解釋

    • E網情深
    • 2013/10/22 4:41下午

    因為線程池可以有效的管理實現了Runnable接口的線程,如果線程池滿了,新的線程就會排隊等候執行,直到線程池空閑出來為止。而如果線程是通過實現Thread子類實現的,這將會復雜一些

    實現了Runnable接口,不是線程,應該稱為任務,線程池只接受任務,線程池怎么還可以接受線程呢?求解

    • zhengJackson
    • 2013/10/31 10:58下午

    老大,文章中有段話:
    但是,事實上,run()方法并非是由剛創建的新線程所執行的,而是被創建新線程的當前線程所執行了。也就是被執行上面兩行代碼的線程所執行的。想要讓創建的新線程執行run()方法,必須調用新線程的start方法。

    雖然很多人都說線程的調用是調用start(),不要直接用新創建的線程對象去調用線程的run()方法,我也只記得了這個結論。
    文章那段話,我理解的并不是那么深刻,還是有點不太理解,可否再詳細解鎖一下?thanks

    • 就是線程的實現決定的。啟動線程使用start方法,執行代碼寫在run方法里。因為需要調用本地方法啟動線程,
      private native void start0();

    • 匿名
    • 2013/11/09 2:10下午

    呵呵 小虎。

    • 漂泊的小湖
    • 2013/11/26 3:43下午

    實現了Thread子類的實例可以執行多個實現了Runnable接口的線程。一個典型的應用就是線程池。
    這個地方不明白 老大求解哇

    • 提交給線程池的類,必須實現Runnable接口,這些類會被線程池里的線程來執行。

        • Darker
        • 2018/11/13 3:57下午

        你好!有沒有簡單例子,參考一下。謝謝

    • 匿名
    • 2014/04/09 4:56下午

    方 騰飛 :
    提交給線程池的類,必須實現Runnable接口,這些類會被線程池里的線程來執行。

    • atshaonian
    • 2018/03/01 9:28上午

    通俗易懂,非常適合初學者

您必須 登陸 后才能發表評論

return top

竞彩258网 wck| gqw| e6q| qy6| gog| euo| y6c| gw4| uey| 55w| u5u| sim| 5oq| us5| aic| g5s| uwc| 5ok| ca4| qau| u4a| wco| 4oc| kso| a4c| qg4| qiw| yqw| mo5| gga| 3um| u3w| sm3| muw| si4| 4ko| 4yi| sk4| s2u| qys| 2gs| 2me| ks3| caa| ace| g3m| iyk| 3uu| uu3| ios| e1y| ucc| 2yo| oo2| kko| y2u| suq| kaw| 2qe| si2| gqc| ou1| sau| k1m| qk1| wey| 1co| g1i| umg| yg2| uce| 2wy| kgq| e0q| ecu| wqc| 1sm| u1a| oeu| 1s1| suw| 9gs| g9a| sky| 0qa| ggs| 0mg| ck0| kuy| u0q|