亚洲国产爱久久全部精品_日韩有码在线播放_国产欧美在线观看_中文字幕不卡在线观看

為何說只有 1 種實現線程的方法?

Java全能學習+面試指南:https://javaxiaobear.cn 今天我們來學習為什么說本質上只有一種實現線程的方式?實現 Runnable 接口究竟比繼承 Thread 類實現線程好在哪里? 實現線程是并發編程中基

Java全能學習+面試指南:https://javaxiaobear.cn

今天我們來學習為什么說本質上只有一種實現線程的方式?實現 Runnable 接口究竟比繼承 Thread 類實現線程好在哪里?

實現線程是并發編程中基礎中的基礎,因為我們必須要先實現多線程,才可以繼續后續的一系列操作。所以本課時就先從并發編程的基礎如何實現線程開始講起,希望你能夠夯實基礎,雖然實現線程看似簡單、基礎,但實際上卻暗藏玄機。首先,我們來看下為什么說本質上實現線程只有一種方式?

實現線程的方式到底有幾種?大部分人會說有 2 種、3 種或是 4 種,很少有人會說有 1 種。我們接下來看看它們具體指什么?2 種實現方式的描述是最基本的,也是最為大家熟知的,我們就先來看看 2 種線程實現方式的源碼。

實現 Runnable 接口

public class RunnableThread implements Runnable {
    @Override
    public void run() {
        System.out.println('用實現Runnable接口實現線程');
    }
}

第 1 種方式是通過實現 Runnable 接口實現多線程,如代碼所示,首先通過 RunnableThread 類實現 Runnable 接口,然后重寫 run() 方法,之后只需要把這個實現了 run() 方法的實例傳到 Thread 類中就可以實現多線程。

繼承 Thread 類

public class ExtendsThread extends Thread {

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

第 2 種方式是繼承 Thread 類,如代碼所示,與第 1 種方式不同的是它沒有實現接口,而是繼承 Thread 類,并重寫了其中的 run() 方法。相信上面這兩種方式你一定非常熟悉,并且經常在工作中使用它們。

線程池創建線程

那么為什么說還有第 3 種或第 4 種方式呢?我們先來看看第 3 種方式:通過線程池創建線程。線程池確實實現了多線程,比如我們給線程池的線程數量設置成 10,那么就會有 10 個子線程來為我們工作,接下來,我們深入解析線程池中的源碼,來看看線程池是怎么實現線程的?

static class DefaultThreadFactory implements ThreadFactory {
 
    DefaultThreadFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
            Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" +
            poolNumber.getAndIncrement() +
            "-thread-";
    }
 

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),
0);

        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}

對于線程池而言,本質上是通過線程工廠創建線程的,默認采用 DefaultThreadFactory ,它會給線程池創建的線程設置一些默認值,比如:線程的名字、是否是守護線程,以及線程的優先級等。但是無論怎么設置這些屬性,最終它還是通過 new Thread() 創建線程的 ,只不過這里的構造函數傳入的參數要多一些,由此可以看出通過線程池創建線程并沒有脫離最開始的那兩種基本的創建方式,因為本質上還是通過 new Thread() 實現的。

在面試中,如果你只是知道這種方式可以創建線程但不了解其背后的實現原理,就會在面試的過程中舉步維艱,想更好的表現自己卻給自己挖了“坑”。

所以我們在回答線程實現的問題時,描述完前兩種方式,可以進一步引申說“我還知道線程池和Callable 也是可以創建線程的,但是它們本質上也是通過前兩種基本方式實現的線程創建。”這樣的回答會成為面試中的加分項。然后面試官大概率會追問線程池的構成及原理,這部分內容會在后面的課時中詳細分析。

有返回值的 Callable 創建線程

class CallableTask implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        return new Random().nextInt();
    }
}

//創建線程池
ExecutorService service = Executors.newFixedThreadPool(10);
//提交任務,并用 Future提交返回結果
Future<Integer> future = service.submit(new CallableTask());

第 4 種線程創建方式是通過有返回值的 Callable 創建線程,Runnable 創建線程是無返回值的,而 Callable 和與之相關的 Future、FutureTask,它們可以把線程執行的結果作為返回值返回,如代碼所示,實現了 Callable 接口,并且給它的泛型設置成 Integer,然后它會返回一個隨機數。

但是,無論是 Callable 還是 FutureTask,它們首先和 Runnable 一樣,都是一個任務,是需要被執行的,而不是說它們本身就是線程。它們可以放到線程池中執行,如代碼所示, submit() 方法把任務放到線程池中,并由線程池創建線程,不管用什么方法,最終都是靠線程來執行的,而子線程的創建方式仍脫離不了最開始講的兩種基本方式,也就是實現 Runnable 接口和繼承 Thread 類。

其他創建方式

定時器 Timer

class TimerThread extends Thread {
//具體實現
}

講到這里你可能會說,我還知道一些其他的實現線程的方式。比如,定時器也可以實現線程,如果新建一個 Timer,令其每隔 10 秒或設置兩個小時之后,執行一些任務,那么這時它確實也創建了線程并執行了任務,但如果我們深入分析定時器的源碼會發現,本質上它還是會有一個繼承自 Thread 類的 TimerThread,所以定時器創建線程最后又繞回到最開始說的兩種方式。

其他方法

/**
 *描述:匿名內部類創建線程
 */
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}).start();

}
}

或許你還會說,我還知道一些其他方式,比如匿名內部類或 lambda 表達式方式,實際上,匿名內部類或 lambda 表達式創建線程,它們僅僅是在語法層面上實現了線程,并不能把它歸結于實現多線程的方式,如匿名內部類實現線程的代碼所示,它僅僅是用一個匿名內部類把需要傳入的 Runnable 給實例出來。

new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
}

我們再來看下 lambda 表達式方式。如代碼所示,最終它們依然符合最開始所說的那兩種實現線程的方式。

實現線程只有一種方式

關于這個問題,我們先不聚焦為什么說創建線程只有一種方式,先認為有兩種創建線程的方式,而其他的創建方式,比如線程池或是定時器,它們僅僅是在 new Thread() 外做了一層封裝,如果我們把這些都叫作一種新的方式,那么創建線程的方式便會千變萬化、層出不窮,比如 JDK 更新了,它可能會多出幾個類,會把 new Thread() 重新封裝,表面上看又會是一種新的實現線程的方式,透過現象看本質,打開封裝后,會發現它們最終都是基于 Runnable 接口或繼承 Thread 類實現的。

接下來,我們進行更深層次的探討,為什么說這兩種方式本質上是一種呢?

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

首先,啟動線程需要調用 start() 方法,而 start() 方法最終還會調用 run() 方法,我們先來看看第一種方式中 run() 方法究竟是怎么實現的,可以看出 run() 方法的代碼非常短小精悍,第 1 行代碼 if (target != null) ,判斷 target 是否等于 null,如果不等于 null,就執行第 2 行代碼 target.run(),而 target 實際上就是一個 Runnable,即使用 Runnable 接口實現線程時傳給Thread類的對象。

然后,我們來看第二種方式,也就是繼承 Thread 方式,實際上,繼承 Thread 類之后,會把上述的 run() 方法重寫,重寫后 run() 方法里直接就是所需要執行的任務,但它最終還是需要調用 thread.start() 方法來啟動線程,而 start() 方法最終也會調用這個已經被重寫的 run() 方法來執行它的任務,這時我們就可以徹底明白了,事實上創建線程只有一種方式,就是構造一個 Thread 類,這是創建線程的唯一方式。

我們上面已經了解了兩種創建線程方式本質上是一樣的,它們的不同點僅僅在于實現線程運行內容的不同,那么運行內容來自于哪里呢?

運行內容主要來自于兩個地方,要么來自于 target,要么來自于重寫的 run() 方法,在此基礎上我們進行拓展,可以這樣描述:本質上,實現線程只有一種方式,而要想實現線程執行的內容,卻有兩種方式,也就是可以通過 實現 Runnable 接口的方式,或是繼承 Thread 類重寫 run() 方法的方式,把我們想要執行的代碼傳入,讓線程去執行,在此基礎上,如果我們還想有更多實現線程的方式,比如線程池和 Timer 定時器,只需要在此基礎上進行封裝即可。

實現 Runnable 接口比繼承 Thread 類實現線程要好

下面我們來對剛才說的兩種實現線程內容的方式進行對比,也就是為什么說實現 Runnable 接口比繼承 Thread 類實現線程要好?好在哪里呢?

首先,我們從代碼的架構考慮,實際上,Runnable 里只有一個 run() 方法,它定義了需要執行的內容,在這種情況下,實現了 Runnable 與 Thread 類的解耦,Thread 類負責線程啟動和屬性設置等內容,權責分明。

第二點就是在某些情況下可以提高性能,使用繼承 Thread 類方式,每次執行一次任務,都需要新建一個獨立的線程,執行完任務后線程走到生命周期的盡頭被銷毀,如果還想執行這個任務,就必須再新建一個繼承了 Thread 類的類,如果此時執行的內容比較少,比如只是在 run() 方法里簡單打印一行文字,那么它所帶來的開銷并不大,相比于整個線程從開始創建到執行完畢被銷毀,這一系列的操作比 run() 方法打印文字本身帶來的開銷要大得多,相當于撿了芝麻丟了西瓜,得不償失。如果我們使用實現 Runnable 接口的方式,就可以把任務直接傳入線程池,使用一些固定的線程來完成任務,不需要每次新建銷毀線程,大大降低了性能開銷。

第三點好處在于 Java 語言不支持雙繼承,如果我們的類一旦繼承了 Thread 類,那么它后續就沒有辦法再繼承其他的類,這樣一來,如果未來這個類需要繼承其他類實現一些功能上的拓展,它就沒有辦法做到了,相當于限制了代碼未來的可拓展性。

綜上所述,我們應該優先選擇通過實現 Runnable 接口的方式來創建線程。 在這里插入圖片描述

【文章轉自:日本站群服務器 http://www.558idc.com/japzq.html處的文章,轉載請說明出處】
聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
發表評論
更多 網友評論0 條評論)
暫無評論

返回頂部

亚洲国产爱久久全部精品_日韩有码在线播放_国产欧美在线观看_中文字幕不卡在线观看

    
    

    欧美激情中文字幕一区二区| 亚洲欧洲视频在线| 免费黄网站欧美| 亚洲精品韩国| 国产一区二区在线免费观看| 欧美成人免费小视频| 亚洲欧美日韩国产综合精品二区| 一区二区视频免费在线观看| 国产精品狠色婷| 欧美精品久久久久久久久久| 久久精品一本| 亚洲欧美在线免费| 亚洲一品av免费观看| 亚洲国产精品悠悠久久琪琪| 国产一区清纯| 国产欧美日韩免费| 国产精品爽爽爽| 欧美性猛片xxxx免费看久爱| 欧美极品在线播放| 欧美电影免费观看| 欧美国产精品专区| 女人香蕉久久**毛片精品| 久久久久久91香蕉国产| 欧美一级在线播放| 亚洲欧洲99久久| 性欧美超级视频| 欧美一区二区日韩一区二区| 亚洲欧美激情四射在线日 | 欧美77777| 久久视频国产精品免费视频在线| 久久国产视频网| 久久国产精品72免费观看| 久久av二区| 久久全球大尺度高清视频| 久久蜜桃av一区精品变态类天堂| 久久精品二区三区| 久久久久久久久综合| 久久久精品五月天| 久久综合给合久久狠狠色| 久久琪琪电影院| 欧美激情视频在线免费观看 欧美视频免费一| 久久视频这里只有精品| 免费在线视频一区| 欧美国产日产韩国视频| 欧美日韩成人在线观看| 国产精品jvid在线观看蜜臀| 国产精品一级在线| 国内精品久久久久影院色| 亚洲国产精品免费| 日韩午夜视频在线观看| 香蕉久久国产| 女女同性精品视频| 欧美午夜一区二区| 国语自产精品视频在线看抢先版结局| 亚洲丰满在线| 午夜激情久久久| 欧美jizz19hd性欧美| 国产精品va在线播放我和闺蜜| 国产午夜精品视频| 99re66热这里只有精品4| 欧美在线免费视屏| 欧美成人精品在线播放| 国产精品入口夜色视频大尺度| 一色屋精品视频免费看| 99精品视频一区二区三区| 久久99伊人| 欧美日韩视频专区在线播放| 国内一区二区在线视频观看| 国产精品99久久久久久久久| 久久一综合视频| 国产精品亚洲精品| 亚洲精品一二三| 久久国内精品自在自线400部| 欧美精品日日鲁夜夜添| 狠狠色噜噜狠狠狠狠色吗综合| 一本到12不卡视频在线dvd| 久久精品国产视频| 国产精品日本| 一区二区久久| 欧美激情a∨在线视频播放| 国产日韩欧美一区二区三区四区| 99pao成人国产永久免费视频| 久久只有精品| 国内精品久久久久伊人av| 亚洲一级黄色| 欧美视频你懂的| 亚洲精品国产精品国自产观看| 久久精品国产综合| 国产精品尤物| 亚洲欧美不卡| 国产精品系列在线| 亚洲无吗在线| 国产精品白丝jk黑袜喷水| 99精品国产在热久久| 欧美久久久久久久久| 99国内精品| 欧美日韩免费观看一区三区| 亚洲精品一区二区三区蜜桃久| 欧美www视频| 在线观看欧美激情| 美乳少妇欧美精品| 亚洲国产成人精品久久久国产成人一区| 久久久国产午夜精品| 国内外成人免费激情在线视频| 欧美一区二区三区视频免费播放| 国产精品一区二区三区久久| 性色av一区二区三区| 国产欧美视频一区二区三区| 久久国产一二区| 伊甸园精品99久久久久久| 久久看片网站| 亚洲精品一品区二品区三品区| 欧美日韩国产成人| 亚洲深夜激情| 国产一区二区av| 免费人成网站在线观看欧美高清| 亚洲韩国精品一区| 欧美日韩在线看| 欧美一级成年大片在线观看| 韩国成人精品a∨在线观看| 欧美成人激情在线| 亚洲香蕉网站| 狠狠色狠狠色综合日日tαg | 国产一区二区三区久久| 久色婷婷小香蕉久久| 一区二区精品国产| 国内久久精品视频| 欧美黄色日本| 亚洲欧洲av一区二区三区久久| 一区在线观看视频| 欧美视频官网| 欧美成年网站| 欧美在线播放一区二区| 亚洲精品国精品久久99热一 | 欧美一区二区在线免费观看| 亚洲国产高清一区二区三区| 国产精品热久久久久夜色精品三区| 久久看片网站| 欧美亚洲视频一区二区| 日韩天天综合| 狠狠噜噜久久| 国产精品亚洲激情| 欧美日韩视频一区二区三区| 久久久999| 亚洲女ⅴideoshd黑人| 亚洲精品老司机| 尤物九九久久国产精品的分类| 欧美午夜一区二区| 欧美黄色aa电影| 麻豆久久久9性大片| 欧美在线视频播放| 亚洲午夜精品国产| 亚洲日本中文| 亚洲成色最大综合在线| 国产农村妇女精品一二区| 欧美视频日韩视频| 欧美精品免费在线观看| 久久久久久97三级| 欧美一级二级三级蜜桃| 亚洲一区二区三区四区五区午夜 | 最新日韩在线视频| 精品成人国产在线观看男人呻吟| 国产精品一区二区你懂得| 国产精品99免费看 | 欧美激情一区二区三区不卡| 久久久久se| 久久精品一区二区三区不卡牛牛| 亚洲在线视频网站| 亚洲一区二区在线视频 | 国产精品电影网站| 欧美视频在线免费看| 欧美日韩精品综合| 欧美揉bbbbb揉bbbbb| 欧美视频在线观看免费| 欧美午夜激情小视频| 国产精品啊v在线| 国产精品美女xx| 国产精品亚洲产品| 韩国成人福利片在线播放| 在线观看91久久久久久| 亚洲国产精品成人综合| 亚洲精品美女在线观看播放| 中文在线资源观看网站视频免费不卡 | 麻豆九一精品爱看视频在线观看免费| 久久久久久久久久久一区| 欧美成人久久| 国产精品久久久久久久久婷婷| 国产精品视频一区二区高潮| 韩国v欧美v日本v亚洲v| 亚洲国产日韩欧美在线图片| 亚洲最新合集| 欧美一区二视频| 欧美gay视频| 国产精品丝袜91| 伊人久久成人| 99精品国产福利在线观看免费| 性xx色xx综合久久久xx| 免费一级欧美在线大片| 国产精品久久久久999| 一区免费观看视频|