1. 程式人生 > >Thread和Runnable的區別

Thread和Runnable的區別

首先講一下程序和執行緒的區別:

  程序:每個程序都有獨立的程式碼和資料空間(程序上下文),程序間的切換會有較大的開銷,一個程序包含1--n個執行緒。

  執行緒:同一類執行緒共享程式碼和資料空間,每個執行緒有獨立的執行棧和程式計數器(PC),執行緒切換開銷小。

  執行緒和程序一樣分為五個階段:建立、就緒、執行、阻塞、終止。

  多程序是指作業系統能同時執行多個任務(程式)。

  多執行緒是指在同一程式中有多個順序流在執行。

在java中要想實現多執行緒,有兩種手段,一種是繼續Thread類,另外一種是實現Runable介面。

一、擴充套件java.lang.Thread類

public class Main {

    public static void main(String[] args) {
        MyThread T1 = new MyThread("A");
        MyThread T2 = new MyThread("B");
        T1.start();
        T2.start();


    }

}

 class MyThread extends Thread {
    private String name;
    public MyThread(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name+":"+i);
            try {
                sleep(1000); //休眠1秒,避免太快導致看不到同時執行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
}

輸出:

A:0 B:0 A:1 B:1 B:2 A:2 B:3 A:3 A:4 B:4

程式啟動執行main時候,java虛擬機器啟動一個程序,主執行緒main在main()呼叫時候被建立。隨著呼叫MitiSay的兩個物件的start方法,另外兩個執行緒也啟動了,這樣,整個應用就在多執行緒下執行。

注意:start()方法的呼叫後並不是立即執行多執行緒程式碼,而是使得該執行緒變為可執行態(Runnable),什麼時候執行是由作業系統決定的。

從程式執行的結果可以發現,多執行緒程式是亂序執行。因此,只有亂序執行的程式碼才有必要設計為多執行緒。

Thread.sleep()方法呼叫目的是不讓當前執行緒獨自霸佔該程序所獲取的CPU資源,以留出一定時間給其他執行緒執行的機會。

實際上所有的多執行緒程式碼執行順序都是不確定的,每次執行的結果都是隨機的。(要看效果要去除sleep方法,然後加大列印次數)

二、實現java.lang.Runnable介面

如果一個類繼承Thread,則不適合資源共享。但是如果實現了Runable介面的話,則很容易的實現資源共享。

public class Main {

    public static void main(String[] args) {

        //測試Runnable
        MyThread1 t1 = new MyThread1();
        new Thread(t1).start();//同一個t1,如果在Thread中就不行,會報錯
        new Thread(t1).start();
        new Thread(t1).start();

    }

}
class MyThread1 implements Runnable{
    private int ticket = 10;
    @Override
    //記得要資源公共,要在run方法之前加上synchronized關鍵字,要不然會出現搶資源的情況
    public synchronized  void  run() {
        for (int i = 0; i <10; i++) {
            if (this.ticket>0) {
                System.out.println("賣票:ticket"+this.ticket--);
            }
        }
        
    }
    
}

輸出:

賣票:ticket10 賣票:ticket9 賣票:ticket8 賣票:ticket7 賣票:ticket6 賣票:ticket5 賣票:ticket4 賣票:ticket3 賣票:ticket2 賣票:ticket1

這裡要注意每個執行緒都是用同一個例項化物件,如果不是同一個,效果就和上面的一樣了!

總結:

實現Runnable介面比繼承Thread類所具有的優勢:

1):適合多個相同的程式程式碼的執行緒去處理同一個資源

2):可以避免java中的單繼承的限制

3):增加程式的健壯性,程式碼可以被多個執行緒共享,程式碼和資料獨立