Java多線(xiàn)程復(fù)習(xí)

首先講一下進(jìn)程和線(xiàn)程的區(qū)別:

  • 進(jìn)程:每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(進(jìn)程上下文),進(jìn)程間的切換會(huì)有較大的開(kāi)銷(xiāo),一個(gè)進(jìn)程包含1--n個(gè)線(xiàn)程。
  • 線(xiàn)程:同一類(lèi)線(xiàn)程共享代碼和數(shù)據(jù)空間,每個(gè)線(xiàn)程有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線(xiàn)程切換開(kāi)銷(xiāo)小。
  • 線(xiàn)程和進(jìn)程一樣分為五個(gè)階段:創(chuàng)建、就緒、運(yùn)行、阻塞、終止。
  • 多進(jìn)程是指操作系統(tǒng)能同時(shí)運(yùn)行多個(gè)任務(wù)(程序)。
  • 多線(xiàn)程是指在同一程序中有多個(gè)順序流在執(zhí)行。

在java中要想實(shí)現(xiàn)多線(xiàn)程,有兩種手段,一種是繼續(xù)Thread類(lèi),另外一種是實(shí)現(xiàn)Runable接口。

擴(kuò)展java.lang.Thread類(lèi)

class Thread1 extends Thread{  
    private String name;  
    public Thread1(String name) {  
       this.name=name;  
    }  
    public void run() {  
        for (int i = 0; i < 5; i++) {  
            System.out.println(name + "運(yùn)行  :  " + i);  
            try {  
                sleep((int) Math.random() * 10);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
         
    }  
}  
public class Main {  
  
    public static void main(String[] args) {  
        Thread1 mTh1=new Thread1("A");  
        Thread1 mTh2=new Thread1("B");  
        mTh1.start();  
        mTh2.start();  
  
    }  
  
}  
輸出:
A運(yùn)行  :  0
B運(yùn)行  :  0
A運(yùn)行  :  1
A運(yùn)行  :  2
A運(yùn)行  :  3
A運(yùn)行  :  4
B運(yùn)行  :  1
B運(yùn)行  :  2
B運(yùn)行  :  3
B運(yùn)行  :  4
再運(yùn)行一下:
A運(yùn)行  :  0
B運(yùn)行  :  0
B運(yùn)行  :  1
B運(yùn)行  :  2
B運(yùn)行  :  3
B運(yùn)行  :  4
A運(yùn)行  :  1
A運(yùn)行  :  2
A運(yùn)行  :  3
A運(yùn)行  :  4

說(shuō)明:
程序啟動(dòng)運(yùn)行main時(shí)候,java虛擬機(jī)啟動(dòng)一個(gè)進(jìn)程,主線(xiàn)程main在main()調(diào)用時(shí)候被創(chuàng)建。隨著調(diào)用MitiSay的兩個(gè)對(duì)象的start方法,另外兩個(gè)線(xiàn)程也啟動(dòng)了,這樣,整個(gè)應(yīng)用就在多線(xiàn)程下運(yùn)行。
注意:
start()方法的調(diào)用后并不是立即執(zhí)行多線(xiàn)程代碼,而是使得該線(xiàn)程變?yōu)榭蛇\(yùn)行態(tài)(Runnable),什么時(shí)候運(yùn)行是由操作系統(tǒng)決定的。
從程序運(yùn)行的結(jié)果可以發(fā)現(xiàn),多線(xiàn)程程序是亂序執(zhí)行。因此,只有亂序執(zhí)行的代碼才有必要設(shè)計(jì)為多線(xiàn)程。
Thread.sleep()方法調(diào)用目的是不讓當(dāng)前線(xiàn)程獨(dú)自霸占該進(jìn)程所獲取的CPU資源,以留出一定時(shí)間給其他線(xiàn)程執(zhí)行的機(jī)會(huì)。
實(shí)際上所有的多線(xiàn)程代碼執(zhí)行順序都是不確定的,每次執(zhí)行的結(jié)果都是隨機(jī)的。


實(shí)現(xiàn)java.lang.Runnable接口

class Thread2 implements Runnable{  
    private String name;  
  
    public Thread2(String name) {  
        this.name=name;  
    }  
  
    @Override  
    public void run() {  
          for (int i = 0; i < 5; i++) {  
                System.out.println(name + "運(yùn)行  :  " + i);  
                try {  
                    Thread.sleep((int) Math.random() * 10);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
          
    }  
      
}  
public class Main {  
  
    public static void main(String[] args) {  
        new Thread(new Thread2("C")).start();  
        new Thread(new Thread2("D")).start();  
    }  
  
}  
輸出:
C運(yùn)行  :  0
D運(yùn)行  :  0
D運(yùn)行  :  1
C運(yùn)行  :  1
D運(yùn)行  :  2
C運(yùn)行  :  2
D運(yùn)行  :  3
C運(yùn)行  :  3
D運(yùn)行  :  4
C運(yùn)行  :  4

說(shuō)明:
Thread2類(lèi)通過(guò)實(shí)現(xiàn)Runnable接口,使得該類(lèi)有了多線(xiàn)程類(lèi)的特征。run()方法是多線(xiàn)程程序的一個(gè)約定。所有的多線(xiàn)程代碼都在run方法里面。Thread類(lèi)實(shí)際上也是實(shí)現(xiàn)了Runnable接口的類(lèi)。
在啟動(dòng)的多線(xiàn)程的時(shí)候,需要先通過(guò)Thread類(lèi)的構(gòu)造方法Thread(Runnable target) 構(gòu)造出對(duì)象,然后調(diào)用Thread對(duì)象的start()方法來(lái)運(yùn)行多線(xiàn)程代碼。
實(shí)際上所有的多線(xiàn)程代碼都是通過(guò)運(yùn)行Thread的start()方法來(lái)運(yùn)行的。因此,不管是擴(kuò)展Thread類(lèi)還是實(shí)現(xiàn)Runnable接口來(lái)實(shí)現(xiàn)多線(xiàn)程,最終還是通過(guò)Thread的對(duì)象的API來(lái)控制線(xiàn)程的,熟悉Thread類(lèi)的API是進(jìn)行多線(xiàn)程編程的基礎(chǔ)。

Thread和Runnable的區(qū)別

如果一個(gè)類(lèi)繼承Thread,則不適合資源共享。但是如果實(shí)現(xiàn)了Runable接口的話(huà),則很容易的實(shí)現(xiàn)資源共享。

總結(jié):
實(shí)現(xiàn)Runnable接口比繼承Thread類(lèi)所具有的優(yōu)勢(shì):
1):適合多個(gè)相同的程序代碼的線(xiàn)程去處理同一個(gè)資源
2):可以避免java中的單繼承的限制
3):增加程序的健壯性,代碼可以被多個(gè)線(xiàn)程共享,代碼和數(shù)據(jù)獨(dú)立
4 ) :main方法其實(shí)也是一個(gè)線(xiàn)程。在java中所以的線(xiàn)程都是同時(shí)啟動(dòng)的,至于什么時(shí)候,哪個(gè)先執(zhí)行,完全看誰(shuí)先得到CPU的資源。
5 ) :在java中,每次程序運(yùn)行至少啟動(dòng)2個(gè)線(xiàn)程。一個(gè)是main線(xiàn)程,一個(gè)是垃圾收集線(xiàn)程。因?yàn)槊慨?dāng)使用java命令執(zhí)行一個(gè)類(lèi)的時(shí)候,實(shí)際上都會(huì)啟動(dòng)一個(gè)JVM,每一個(gè)jVM就是在操作系統(tǒng)中啟動(dòng)了一個(gè)進(jìn)程。

線(xiàn)程狀態(tài)轉(zhuǎn)換

線(xiàn)程狀態(tài).jpg

(未完待續(xù))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容