java線程(上)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):增加程序的健壯性,代碼可以被多個線程共享,代碼和數據獨立

 


免責聲明!

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



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