Java知多少(58)線程Runnable介面和Thread類詳解

來源:互聯網
上載者:User

標籤:

大多數情況,通過執行個體化一個Thread對象來建立一個線程。Java定義了兩種方式:

  • 實現Runnable 介面;
  • 可以繼承Thread類。


下面的兩小節依次介紹了每一種方式。

實現Runnable介面

建立線程的最簡單的方法就是建立一個實現Runnable 介面的類。Runnable抽象了一個執行代碼單元。你可以通過實現Runnable介面的方法建立每一個對象的線程。為實現Runnable 介面,一個類僅需實現一個run()的簡單方法,該方法聲明如下:
    public void run( )
在run()中可以定義代碼來構建新的線程。理解下面內容是至關重要的:run()方法能夠像主線程那樣調用其他方法,引用其他類,聲明變數。僅有的不同是run()在程式中確立另一個並發的線程執行入口。當run()返回時,該線程結束。

在你已經建立了實現Runnable介面的類以後,你要在類內部執行個體化一個Thread類的對象。Thread 類定義了好幾種建構函式。我們會用到的如下:
    Thread(Runnable threadOb, String threadName)
該建構函式中,threadOb是一個實現Runnable介面類的執行個體。這定義了線程執行的起點。新線程的名稱由threadName定義。

建立新的線程後,它並不運行直到調用了它的start()方法,該方法在Thread 類中定義。本質上,start() 執行的是一個對run()的調用。 Start()方法聲明如下:

1 void start( )

下面的例子是建立一個新的線程並啟動它運行:

 1 // Create a second thread. 2 class NewThread implements Runnable { 3     Thread t; 4     NewThread() { 5         // Create a new, second thread 6         t = new Thread(this, "Demo Thread"); 7         System.out.println("Child thread: " + t); 8         t.start(); // Start the thread 9     }10 11     // This is the entry point for the second thread.12     public void run() {13         try {14             for(int i = 5; i > 0; i--) {15                 System.out.println("Child Thread: " + i);16                 Thread.sleep(500);17             }18         } catch (InterruptedException e) {19             System.out.println("Child interrupted.");20         }21         System.out.println("Exiting child thread.");22     }23 }24 25 class ThreadDemo {26     public static void main(String args[]) {27         new NewThread(); // create a new thread28         try {29             for(int i = 5; i > 0; i--) {30                 System.out.println("Main Thread: " + i);31                 Thread.sleep(1000);32             }33         } catch (InterruptedException e) {34            System.out.println("Main thread interrupted.");35         }36         System.out.println("Main thread exiting.");37     }38 }

在NewThread 建構函式中,新的Thread對象由下面的語句建立::

1     t = new Thread(this, "Demo Thread");

通過前面的語句this 表明在this對象中你想要新的線程調用run()方法。然後,start() 被調用,以run()方法為開始啟動了線程的執行。這使子線程for 迴圈開始執行。調用start()之後,NewThread 的建構函式返回到main()。當主線程被恢複,它到達for 迴圈。兩個線程繼續運行,共用CPU,直到它們的迴圈結束。該程式的輸出如下:

 1 Child thread: Thread[Demo Thread,5,main] 2 Main Thread: 5 3 Child Thread: 5 4 Child Thread: 4 5 Main Thread: 4 6 Child Thread: 3 7 Child Thread: 2 8 Main Thread: 3 9 Child Thread: 110 Exiting child thread.11 Main Thread: 212 Main Thread: 113 Main thread exiting.

如前面提到的,在多線程程式中,通常主線程必須是結束啟動並執行最後一個線程。實際上,一些老的JVM,如果主線程先於子線程結束,Java的已耗用時間系統就可能“掛起”。前述程式保證了主線程最後結束,因為主線程沉睡周期1000毫秒,而子線程僅為500毫秒。這就使子線程在主線程結束之前先結束。簡而言之,你將看到等待線程結束的更好途徑。

擴充Thread

建立線程的另一個途徑是建立一個新類來擴充Thread類,然後建立該類的執行個體。當一個類繼承Thread時,它必須重載run()方法,這個run()方法是新線程的入口。它也必須調用start()方法去啟動新線程執行。下面用擴充thread類重寫前面的程式:

 1 // Create a second thread by extending Thread 2 class NewThread extends Thread { 3     NewThread() { 4         // Create a new, second thread 5         super("Demo Thread"); 6         System.out.println("Child thread: " + this); 7         start(); // Start the thread 8     } 9 10     // This is the entry point for the second thread.11     public void run() {12         try {13             for(int i = 5; i > 0; i--) {14                 System.out.println("Child Thread: " + i);15                 Thread.sleep(500);16             }17         } catch (InterruptedException e) {18             System.out.println("Child interrupted.");19         }20         System.out.println("Exiting child thread.");21     }22 }23 24 class ExtendThread {25     public static void main(String args[]) {26         new NewThread(); // create a new thread27         try {28             for(int i = 5; i > 0; i--) {29                 System.out.println("Main Thread: " + i);30                 Thread.sleep(1000);31            }32         } catch (InterruptedException e) {33             System.out.println("Main thread interrupted.");34         }35         System.out.println("Main thread exiting.");36     }37 }

該程式產生和前述版本相同的輸出。子線程是由執行個體化NewThread對象產生的,該對象從Thread類派生。注意NewThread 中super()的調用。該方法調用了下列形式的Thread建構函式:

1     public Thread(String threadName)

這裡,threadName指定線程名稱。

選擇合適方法

到這裡,你一定會奇怪為什麼Java有兩種建立子線程的方法,哪一種更好呢。所有的問題都歸於一點。Thread類定義了多種方法可以被衍生類別重載。對於所有的方法,惟一的必須被重載的是run()方法。這當然是實現Runnable介面所需的同樣的方法。很多Java程式員認為類僅在它們被加強或修改時應該被擴充。因此,如果你不重載Thread的其他方法時,最好只實現Runnable 介面。這當然由你決定。然而,在本章的其他部分,我們應用實現runnable介面的類來建立線程。

系列文章:

Java知多少(上)

Java知多少(39)interface介面

Java知多少(40)介面和抽象類別的區別

Java知多少(41)泛型詳解

Java知多少(42)泛型萬用字元和型別參數的範圍

Java知多少(43)異常處理基礎

Java知多少(44)異常類型

Java知多少(45)未被捕獲的異常

Java知多少(46)try和catch的使用

Java知多少(47)多重catch語句的使用

Java知多少(48)try語句的嵌套

Java知多少(49)throw:異常的拋出

Java知多少(50)Java throws子句

Java知多少(51)finally

Java知多少(52)內建異常

Java知多少(53)使用Java建立自己的異常子類

Java知多少(54)斷言詳解

Java知多少(55)線程

Java知多少(56)執行緒模式Java知多少(57)主線程

Java知多少(58)線程Runnable介面和Thread類詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.