認識多線程

目錄

 

一 、進程 與 線程

二 、Java中多線程的實現

 1 、繼承 Thread 類實現多線程

 2 、實現 Runnable 接口實現多線程

三 、通過 Thread 類 和 Runnable 接口實現多線程的區別

 1 、繼承 Thread 類不能資源共享

2 、實現 Runnable 接口實現資源共享


 

一 、進程 與 線程

進程是程序的一次動態的執行過程。多進程系統可以同時運行多個進程(也就是程序),而線程是比進程更小的執行單位,比如運行一個聽歌的軟件(進程),播放歌曲就是其中一個線程,搜索歌曲也是一個線程,瀏覽評論也是一個線程

多線程是指一個進程在執行過程中可以產生多個線程,這些線程可以同時存在,同時運行,所以一個進程可能包含了多個同時執行的線程。

多線程是實現併發機制的一種有效手段

 

二 、Java中多線程的實現

在Java中要想實現多線程代碼有兩種方法:

【1】繼承 Thread 類

【2】實現 Runnable 接口

 1 、繼承 Thread 類實現多線程

Thread 類是在Java.lang包中定義,一個類如果繼承了 Thread 類,此類就稱爲多線程操作類,在Thread子類中,必須明確地覆寫 run() 方法,並通過 start() 方法啓動線程

class MyThread extends Thread{  //繼承Thread類
    private String name;
    public MyThread(String name){
        this.name = name;
    }
    public void run(){    //覆寫Thread類中的run()方法
        for (int i=0; i<10; i++){
            System.out.println(name + "運行,i = " + i);
        }
    }
}

public class ThreadDemo01 {
    public static void main(String[] args) {
        MyThread mt1 = new MyThread("線程A");
        MyThread mt2 = new MyThread("線程B");
        mt1.start();   //調用start()方法啓動線程
        mt2.start();   //調用start()方法啓動線程
    }
}

程序運行結果(可能的一種結果):

從程序的運行結果可以發現,兩個線程交替運行,哪個線程對象搶到了CPU資源,哪個線程就可以運行,所以程序每次的運行結果都不一樣

提問:爲什麼啓動線程必須通過start()方法啓動,而不能直接調用 run() 方法呢?

回答:由於多線程的實現需要依靠底層操作系統得支持,start() 方法除了會調用run() 方法,還有一些調用本機操作系統的函數。另外,一個線程對象只能調用一次start()方法,調用一次便可以啓動多線程,如果調用多次,則會拋出異常

 繼承 Thread 類可以實現多線程,但會受到單繼承侷限的影響,所以,還可以通過實現Runnable接口實現多線程

 

 

 2 、實現 Runnable 接口實現多線程

查閱JDK文檔發現,Runnable 接口只定義了一個 run() 方法

要想啓動一個多線程必須使用 start() 方法完成,那麼此時該如何啓動多線程呢?

查閱JDK文檔的Thread類發現其有構造方法可以接收Runnable的子類實例對象,所以就可以依靠此點啓動多線程

實現Runnable接口,通過Thread類啓動多線程

class MyThread implements Runnable{  //實現Runnable接口
    private String name;
    public MyThread(String name){
        this.name = name;
    }
    public void run(){    //覆寫Runnable接口中的run()方法
        for (int i=0; i<10; i++){
            System.out.println(name + "運行,i = " + i);
        }
    }
}

public class RunnableDemo01 {
    public static void main(String[] args) {
        MyThread mt1 = new MyThread("線程C"); //實例化Runnable子類對象
        MyThread mt2 = new MyThread("線程D"); //實例化Runnable子類對象
        Thread t1 = new Thread(mt1);     //實例化Thread類對象
        Thread t2 = new Thread(mt2);     //實例化Thread類對象
        t1.start();     //啓動線程
        t2.start();     //啓動線程
    }
}

程序運行結果(可能的一種結果):

 

 

三 、通過 Thread 類 和 Runnable 接口實現多線程的區別

 使用 Thread 類實現多線程時無法實現資源共享,而實現 Runnable 接口實現多線程可以實現資源共享

 1 、繼承 Thread 類不能資源共享

class MyThread extends Thread{
    private int ticket = 5;  //一共有5張票
    public void run(){
        for (int i=0; i<100; i++){
           if (ticket>0){   //判斷是否有餘票
               System.out.println("賣票:ticket = " + ticket--);
           }
        }
    }
}

public class ThreadDemo02 {
    public static void main(String[] args) {
        MyThread mt1 = new MyThread();
        MyThread mt2 = new MyThread();
        MyThread mt3 = new MyThread();
        mt1.start();
        mt2.start();
        mt3.start();
    }
}

程序運行結果:

從程序的運行結果可以發現,每個線程都各自賣自己的5張票,沒有達到資源共享

 

2 、實現 Runnable 接口實現資源共享

class MyThread implements Runnable{
    private int ticket = 5; //一共5張票
    public void run(){
        for (int i=0; i<100; i++){
            if (ticket>0){  //判斷是否有餘票
                System.out.println("賣票:ticket = " + ticket--);
            }
        }
    }
}

public class RunnableDemo02 {
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        //啓動3個線程
        new Thread(mt).start();
        new Thread(mt).start();
        new Thread(mt).start();
    }
}

程序運行結果:

3個線程一共賣了5張票

 

實現 Runnable 接口相對於繼承 Thread類來說,有如下優勢:

【1】適合多個相同程序代碼的線程去處理同一資源的情況

【2】可以避免由於Java的單繼承特性帶來的侷限

【3】增強了程序的健壯性,代碼能夠被多個線程共享,代碼與數據是獨立的

所以在開發中建議使用 Runnable 接口實現多線程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章