一、繼承Thread類創建線程類
Java使用Thread類代表線程,所有的線程對象都必須是Thread類或其子類的實例。每個線程的作用是完成一定的任務,實際上就是執行一段程序流即一段順序執行的代碼。Java使用線程執行體來代表這段程序流。
Thread類的聲明如下:
public class Thread implements Runnable {}
可以看到,Thread本身就實現了Runnable接口。
Java中通過繼承Thread類來創建並啟動多線程的步驟如下:
01. 定義Thread類的子類,並重寫該類的run()方法,該run()方法的方法體就代表了線程需要完成的任務,因此把run()方法稱為線程執行體。
02. 創建Thread子類的實例,即創建了線程對象。
03. 調用線程對象的start()方法來啟動該線程。
示例:
package com.demo; //通過繼承Thread類來創建線程類 public class MyThread extends Thread{ private int ticket = 10; //重寫run方法 public void run(){ for(int i=0;i<20;i++){ if(this.ticket>0){ System.out.println(this.getName()+" 賣票:ticket"+this.ticket--); } } } public static void main(String[] args) { // 啟動3個線程t1,t2,t3;每個線程各賣10張票! MyThread t1=new MyThread(); MyThread t2=new MyThread(); MyThread t3=new MyThread(); t1.start(); t2.start(); t3.start(); } }
運行結果:
Thread-0 賣票:ticket10 Thread-0 賣票:ticket9 Thread-0 賣票:ticket8 Thread-0 賣票:ticket7 Thread-1 賣票:ticket10 Thread-1 賣票:ticket9 Thread-1 賣票:ticket8 Thread-1 賣票:ticket7 Thread-1 賣票:ticket6 Thread-0 賣票:ticket6 Thread-0 賣票:ticket5 Thread-0 賣票:ticket4 Thread-0 賣票:ticket3 Thread-0 賣票:ticket2 Thread-0 賣票:ticket1 Thread-2 賣票:ticket10 Thread-2 賣票:ticket9 Thread-2 賣票:ticket8 Thread-2 賣票:ticket7 Thread-2 賣票:ticket6 Thread-2 賣票:ticket5 Thread-2 賣票:ticket4 Thread-2 賣票:ticket3 Thread-2 賣票:ticket2 Thread-1 賣票:ticket5 Thread-2 賣票:ticket1 Thread-1 賣票:ticket4 Thread-1 賣票:ticket3 Thread-1 賣票:ticket2 Thread-1 賣票:ticket1
結果說明:
(01) MyThread繼承於Thread,它是自定義個線程。每個MyThread都會賣出10張票。
(02) 主線程main創建並啟動3個MyThread子線程。每個子線程都各自賣出了10張票。
二、實現Runnable接口創建線程類
Runnable 是一個接口,該接口中只包含了一個run()方法。它的定義如下:
public interface Runnable { public abstract void run(); }
實現Runnable接口來創建並啟動多線程的步驟如下:
01. 定義Runnable接口的實現類,並重寫該接口的run()方法,該run()方法的方法體同樣是該線程的線程執行體。
02. 創建Runnable實現類的實例,並以此實例作為Thread的target來創建Thread對象,該Thread對象才是真正的線程對象。
03. 調用線程對象的start()方法來啟動線程。
需要注意的是:Runnable對象僅僅作為Thread對象的target,Runnable實現類里包含的run()方法僅作為線程執行體。而實際的線程對象依然是Thread實例,只是該Thread線程負責執行其target的run()方法。
示例:
package com.demo; //通過實現Runnable接口創建多線程 public class MyThread1 implements Runnable{ private int ticket = 10; public void run(){ for(int i=0;i<20;i++){ if(this.ticket>0){ System.out.println(Thread.currentThread().getName()+" 賣票:ticket"+this.ticket--); } } } public static void main(String[] args) { MyThread1 mt=new MyThread1(); // 啟動3個線程t1,t2,t3(它們共用一個Runnable對象),這3個線程一共賣10張票! Thread t1=new Thread(mt); Thread t2=new Thread(mt); Thread t3=new Thread(mt); t1.start(); t2.start(); t3.start(); } }
運行結果:
Thread-0 賣票:ticket10 Thread-0 賣票:ticket8 Thread-0 賣票:ticket7 Thread-1 賣票:ticket9 Thread-2 賣票:ticket5 Thread-0 賣票:ticket6 Thread-1 賣票:ticket4 Thread-2 賣票:ticket3 Thread-1 賣票:ticket1 Thread-0 賣票:ticket2
結果說明:
(01) 和上面“MyThread繼承於Thread”不同;這里的MyThread1實現了Thread接口。
(02) 主線程main創建並啟動3個子線程,而且這3個子線程都是基於“mt這個Runnable對象”而創建的。運行結果是這3個子線程一共賣出了10張票。這說明它們是共享了MyThread接口的。
三、Thread和Runnable的異同點
Thread 和 Runnable 的相同點:都是“多線程的實現方式”。
Thread 和 Runnable 的不同點:
Thread 是類,而Runnable是接口;Thread本身是實現了Runnable接口的類。我們知道“一個類只能有一個父類,但是卻能實現多個接口”,因此Runnable具有更好的擴展性。
此外,Runnable還可以用於“資源的共享”。即,多個線程都是基於某一個Runnable對象建立的,它們會共享Runnable對象上的資源。
通常,建議通過“Runnable”實現多線程!