Java多線程(二)——常用的實現多線程的兩種方式


一、繼承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”實現多線程!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM