實現多線程的正確姿勢

網上和書籍的各種說法:魚龍混雜

在這裏插入圖片描述

正確的說法

在這裏插入圖片描述

方法一:實現Runnable接口

package threadcoreknowledge.createthreads;

/**
 * 描述:     用Runnable方式創建線程
 */
public class RunnableStyle implements Runnable{

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

    @Override
    public void run() {
        System.out.println("用Runnable方法實現線程");
    }
}

方法二:繼承Thread

package threadcoreknowledge.createthreads;

/**
 * 描述:     用Thread方式實現線程
 */
public class ThreadStyle extends Thread{

    @Override
    public void run() {
        System.out.println("用Thread類實現線程");
    }

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

實現Runnable接口更好一些原因如下:

run方法源碼解析:

    /* What will be run. */
    private Runnable target;

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


實現Runnable接口最終會調用 target.run() 但是繼承Thread類的run方法整個都被重寫。

繼承Thread有如下缺點:

1、從代碼的架構考慮的話:run方法裏面的內容(對應我們具體執行的任務),它應該和我們和線程的創建、運行等機制也就是Thread類是解耦的,所以不應該把這兩個事情混爲一談,從解耦的角度是有缺點的。
2、如果說繼承了Thread類,用這種方法的話,每次如果我們需要新建一個任務,只能去新建一個獨立的線程,而新建一個獨立的線程這樣的損耗是比較大的,需要創建、執行、銷燬等,而如果使用Runnable接口的話,後面就會使用線程池等一些工具,就可以大大減小創建線程帶來的損耗,從資源節約的角度上也是優缺點的。
3、Java不支持多繼承,如果繼承了Thread類就不可以再去繼承其他的類,大大限制了可擴展性。

同時使用這兩種方法會怎麼樣:

/**
 * 描述:     同時使用Runnable和Thread兩種實現線程的方式
 */
public class BothRunnableThread {

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我來自Runnable");
            }
        }) {
            @Override
            public void run() {
                System.out.println("我來自Thread");
            }
        }.start();
    }
}

運行之後:
在這裏插入圖片描述
分析:這是因爲run方法被重寫了,這是target.run就不會執行了。

在這裏插入圖片描述

常見錯誤觀點:

1、“線程池創建線程也是一種新建線程的方式”
雖然利用線程成可以創建線程,但是這只是表象,不屬於創建線程的本質。通過深入Executors的源碼可以看到,在線程池的內部,也是新建了Thread類來執行這些任務的。
在這裏插入圖片描述
2、“通過Callable和FutureTAsk創建線程,也算是一種新建線程的方式。”
3、“無返回值是實現runnable接口,有返回值是實現callable接口,所以callable是新的實現線程的方式”
4、“匿名內部類”
5、“Lambda表達式”

綜上所述,這些錯誤觀點的本質都是離不開Runnable接口和Thread類的。都屬於表明現象。多線程的實現方式,在代碼中寫法千變萬化,但本質不變。

常見面試題。

在這裏插入圖片描述

在這裏插入圖片描述

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