1.建立多執行緒的兩種方式

1.通過繼承Thread類實現多執行緒

class MyThread extends Thread{
    //重寫run方法
    public void run(){

    }
}



//測試類:建立執行緒
    Thread thread01 = new MyThread();
    Thread thread02 = new MyThread();

2.通過實現Runnable介面實現多執行緒

class MyThread implements Runnable{
    //實現run()方法
    public void run(){

    }
}

//測試類:建立執行緒
    MyThread myThread= new MyThread();
    Thread thread01 = new Thread(myThread);
    Thread thread02 = new Thread(myThread);


由實現類不難看出,通過繼承方式建立的兩條執行緒建立了兩個MyThread類的物件

MyThread01 myThread01 = new MyThread01();
myThread01.setName(“視窗一”);
MyThread01 myThread02 = new MyThread01();
myThread02.setName(“視窗二”);

而通過介面建立的兩條執行緒只建立了一個MyThread類物件myThread

MyThread02 myThread = new MyThread02();
Thread thread01 = new Thread(myThread);
thread01.setName(“視窗一”);
Thread thread02 = new Thread(myThread);
thread02.setName(“視窗二”);

那麼這兩種方式建立的執行緒有什麼區別呢?我們通過下面的例子來觀察一下!

  • 用多執行緒模擬多個視窗售票,實現執行緒安全。
//MyThread01:
public class MyThread01 extends Thread {
    /*
     * 通過繼承Thread類建立多執行緒 
     * 模擬多個視窗實現售票
     */
    Object o = new Object();
    int i = 10;// 共有10張票

    @Override
    public void run() {
        while (true) {
            synchronized (o) {
                if (i > 0) {
                    System.out.println(Thread.currentThread().getName() + "售出了第" + i + "張票");
                    i--;
                }
            }
        }
    }
}
//測試類
public class Test01 {
    public static void main(String[] args) {
        // 建立名為視窗一和視窗二的兩個執行緒
        MyThread01 myThread01 = new MyThread01();
        myThread01.setName("視窗一");

        MyThread01 myThread02 = new MyThread01();
        myThread02.setName("視窗二");

        // 開啟執行緒
        myThread01.start();
        myThread02.start();

    }
}

執行結果:
這裡寫圖片描述

public class MyThread02 implements Runnable {
    /*
     * 通過implements實現Runnable介面建立多執行緒 模擬多個視窗實現售票
     */

    Object o = new Object();
    int i = 10;// 共100張票

    @Override
    public void run() {
        while (true) {
            synchronized (o) {
                if (i > 0) {
                    System.out.println(Thread.currentThread().getName() + "售出了第" + i + "張票");
                    i--;
                }
            }
        }
    }
}
//測試類:
public class Test02 {
    public static void main(String[] args) {
        // 建立多執行緒
        MyThread02 myThread = new MyThread02();
        Thread thread01 = new Thread(myThread);
        thread01.setName("視窗一");

        Thread thread02 = new Thread(myThread);
        thread02.setName("視窗二");

        // 開啟執行緒
        thread01.start();
        thread02.start();

    }
}

執行截圖:
這裡寫圖片描述

通過觀察兩種方式建立多執行緒實現執行緒安全的執行截圖可以看出:通過繼承Thread類建立多執行緒,每個執行緒都執行了10次,並沒有實現執行緒安全;而通過實現Runnable介面建立的兩個執行緒,一共執行了10次,實現了執行緒安全。
造成這種去別的原因是什麼呢?
其實是因為如上文所說,通過繼承Thread類建立的多執行緒,每個執行緒都建立了一個MyThread類的物件,所以創建出來的多個執行緒相互之間互不影響,不受synchronized關鍵字的約束,所以也就無法實現執行緒安全。
而通過實現Runnable介面建立的多個執行緒,只建立了一個MyThread類的物件,多個執行緒之間互相影響,共享同一個MyThread類物件,受到synchronized關鍵字的約束,實現了繼承安全。

2.兩種方式建立多執行緒的優缺點及其區別

1.通過繼承Thread類建立多執行緒:

  • 優點:編寫簡單
  • 缺點:無法繼承其他父類

2.通過實現Runnable介面建立多執行緒

  • 優點:可以繼承其他類,多執行緒可以共享一個程序
  • 缺點:程式設計方式稍微複雜,如果需要訪問當前執行緒物件的引用,需要呼叫Thread.currentThread()方法

區別:兩種方式建立多執行緒最大的區別就是:通過實現Runnable介面建立的多執行緒共享同一個程序,同一個變數。
而通過繼承Thread類實建立,必須通過第三方才能實現執行緒安全!