多線程的8大基礎核心——實現多線程的幾種方法

1、實現多線程一共有兩種方法(官方文檔這麼說的)

(1)聲明類是Thread的子類(即繼承Thread),不推薦使用這種方法

缺點:從代碼架構角度去考慮,run()方法就是我們具體執行的內容,run()方法的執行應該與我們線程(Thread)的創建、執行是解耦的,不應該把二者混爲一談。

繼承Thread實現線程,這種時候我們每次新建一個任務,只能去創建一個新的線程,而線程的創建、執行、銷燬是十分消耗資源的,但是通過實現Runnable接口的方法,我們就可以利用線程池之類的工具,可以大大減小資源的消耗。

Java是不允許雙繼承的,一旦繼承Thread,就無法繼承其他的類,是的類的擴展性降低。

public class ThreadStyle extends Thread {
    @Override
    public void run() {
        System.out.println("通過集成Thread類實現多線程");
    }

    public static void main(String[] args) {
        new ThreadStyle().start();
    }
}

(2)聲明一個實現Runnable接口的類,然後實現run()方法(即實現Runnable接口),這個方法相對更好。

public class RunnableStyle implements Runnable {
    @Override
    public void run() {
        System.out.println("通過實現Runnable接口實現多線程");
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new RunnableStyle());
        t1.start();
    }
}

以上兩種方法都是執行run(),只不過run()的來源不同,以下是Thread類原本run()方法的代碼

@Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

上面代碼中的target就是Runnbale(第二種方法在創建線程的時候,傳入的)

用第一種方法實現線程的時候,因爲要重寫run()方法,所以線程最後執行的方法run()是我們重寫的run()方法。

用第二種方法實現線程的時候,因爲要執行所傳入的Runnable的run()方法,所以線程最後執行的run()方法是我們實現的run()方法。

 

3、同時使用兩種實現線程的方式會怎麼樣

4、網上錯誤觀點

(1)線程池創建線程也算是一種新建線程的方式

錯誤原因:線程池創建線程的原理也是使用的new Thread()的方式

(2)通過Callable和FutureTask創建線程,也算是一種新建線程的方式

錯誤原因:

(3)定時器

(4)匿名內部類

(5)Lambda表達式

網上創建線程的方式多種多樣,但是其本質只有以上兩種創建線程的方式。

5、實現多線程的常見面試問題

問題1:有多少種實現線程的方法

從不同的角度看,會有不同的答案。

1)典型回答:兩種;一種是繼承Thread類;另一種是實現Runnable接口(這種方式實現更好),但是看原理,這兩種方式的本質是一樣的,因爲run()方法的代碼如下,(代碼省略),這f兩種方法都是基於Thread的run()方法實現的,只不過一種是重寫run()方法,一種是通過執行run()方法中的target.run()去實現的。

總結回答:從本質上講只有一種,都需要新建Thread類,但是通常我們區分爲兩種方法,一種是繼承Thread類,一種是實現Runnable接口,另外還有一些外在形式(代碼實現上)上去實現多線程,如線程池、計時器等。

問題2:實現Runnable接口和繼承Thread類那種方式更好

1)從代碼架構角度:這裏其實是分有兩件事情的,一就是具體的任務,也就是run()方法要執行的內容;二就是跟線程的生命週期相關的,如創建、運行、銷燬線程,而這件事情應該是Thread類應該去做的事情,這兩件事情的目的不也一樣,從代碼架構角度看,應該解耦,所以事先Runnable接口的方法更好點。

2)新建線程的損耗:如果我們使用繼承Thread這種方式去實現線程,那麼每次我們想要新建啓動一個任務,都需要new 一個Thread類,這樣損耗比較大,每一次都需要經過創建和銷燬線程的步驟,但是如果,我們通過實現Runnable接口這種方式去實現多線程的話,就可以通過線程池中的線程去執行任務,同一個線程可以被重複使用,這樣就減少了在線程在創建和銷燬上的消耗。

3)Java不支持雙繼承:一旦繼承了Thread類,就無法再去繼承其他的類,會降低程序的可擴展性,比如我們要繼承一個基類。

 

 

 

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