亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

一文帶你深入剖析Java線程池的前世今生

 更新時間:2022年10月18日 08:14:26   作者:一無是處的研究僧  
這篇文章主要帶大家介紹了深入剖析一下Java線程池的前世今生,了解線程池的原理以及為什么需要線程池。文中的示例代碼講解詳細,需要的可以參考一下

由線程到線程池

線程在做什么

靈魂拷問:寫了那么多代碼,你能夠用一句話簡練描述線程在干啥嗎?

public?class?Demo01?{

??public?static?void?main(String[]?args)?{
????var?thread?=?new?Thread(()?->?{
??????System.out.println("Hello?world?from?a?Java?thread");
????});
????thread.start();
??}
}

我們上面的這個用線程輸出字符串的代碼來進行說明。我們知道上面的Java代碼啟動了一個線程,然后執(zhí)行lambda函數(shù),在以前沒有lambda表達式的時候我們可以使用匿名內(nèi)部類實現(xiàn),向下面這樣。

public?class?Demo01?{

??public?static?void?main(String[]?args)?{
????var?thread?=?new?Thread(new?Runnable()?{
??????@Override
??????public?void?run()?{
????????System.out.println("Hello?world?from?a?Java?thread");
??????}
????});
????thread.start();
??}
}

但是本質(zhì)上Java編譯器在編譯的時候都認為傳遞給他的是一個對象,然后執(zhí)行對象的run方法。剛剛我們使用的Thread的構(gòu)造函數(shù)如下:

????public?Thread(Runnable?target)?{
????????this(null,?target,?"Thread-"?+?nextThreadNum(),?0);
????}

Thread在拿到這個對象的時候,當(dāng)我們執(zhí)行Threadstart方法的時候,會執(zhí)行到一個native方法start0

當(dāng)JVM執(zhí)行到這個方法的時候會調(diào)用操作系統(tǒng)給上層提供的API創(chuàng)建一個線程,然后這個線程會去解釋執(zhí)行我們之前給Thread對象傳入的對象的run方法字節(jié)碼,當(dāng)run方法字節(jié)碼執(zhí)行完成之后,這個線程就會退出。

看到這里我們仔細思考一下線程在做一件什么樣的事情,JVM給我們創(chuàng)建一個線程好像執(zhí)行完一個函數(shù)(run)的字節(jié)碼之后就退出了,線程的生命周期就結(jié)束了。確實是這樣的,JVM給我們提供的線程就是去完成一個函數(shù),然后退出(記住這一點,這一點很重要,為你后面理解線程池的原理有很大的幫助)。事實上JVM在使用操作系統(tǒng)給他提供的線程的時候也是給這個線程傳遞一個函數(shù)地址,然后讓這個線程執(zhí)行完這個函數(shù)。只不過JVM給操作系統(tǒng)傳遞的函數(shù),這個函數(shù)的功能就是去解釋執(zhí)行字節(jié)碼,當(dāng)解釋執(zhí)行字節(jié)碼完成之后,這個函數(shù)也會退出(被系統(tǒng)回收)。

看到這里可以將線程的功能總結(jié)成一句話:執(zhí)行一個函數(shù),當(dāng)這個函數(shù)執(zhí)行完成之后,線程就會退出,然后被回收,當(dāng)然這個函數(shù)可以調(diào)用其他的函數(shù),可能你會覺得這句話非常簡單,但是這句話會我們理解線程池的原理非常有幫助。

為什么需要線程池

上面我們已經(jīng)談到了,當(dāng)我們執(zhí)行start的方法的時候,最終會走到start0方法,這是一個native方法,JVM在執(zhí)行這個方法的時候會通過系統(tǒng)底層函數(shù)創(chuàng)建一個線程,然后去執(zhí)行run方法,這里需要注意,創(chuàng)建線程是需要系統(tǒng)資源的,比如說內(nèi)存,因為操作系統(tǒng)是系統(tǒng)資源的管理者,因此一般需要系統(tǒng)資源的方法都需要操作系統(tǒng)的參與,因此創(chuàng)建線程需要操作系統(tǒng)的幫忙,而一旦需要操作系統(tǒng)介入,執(zhí)行代碼的狀態(tài)就需要從用戶態(tài)到內(nèi)核態(tài)轉(zhuǎn)換(內(nèi)核態(tài)能夠執(zhí)行許多用戶態(tài)不能夠執(zhí)行的指令),當(dāng)操作系統(tǒng)創(chuàng)建完線程之后有需要返回用戶態(tài),我們的代碼將繼續(xù)被執(zhí)行,整個過程像下面這樣。

從上圖可以看到我們需要兩次的上下文切換,同時還需要執(zhí)行一些操作系統(tǒng)的函數(shù),這個過程是非常耗時間的,如果在并發(fā)非常高的情況,我們頻繁的去生成線程然后銷毀,這對我們程序的性能影響還是非常大的。因此許許多多聰明的程序員就想能不能不去頻繁的創(chuàng)建線程而且也能夠完成我們的功能——我們創(chuàng)建線程的目的就是想讓我們的程序完成的更加快速,讓多個不同的線程同時執(zhí)行不同的任務(wù)。于是線程池就被創(chuàng)造出來了。線程池的結(jié)構(gòu)大致如下所示:

線程池實現(xiàn)原理

在前面我們已經(jīng)提到了關(guān)于線程池和線程比較重要的兩個點:

  • 線程就是執(zhí)行一個函數(shù)。
  • 線程池當(dāng)中的線程可以執(zhí)行很多函數(shù),但是不會退出。

憑借你樸素的情感,你覺得如何實現(xiàn)上面兩個要求。答案就是在一個函數(shù)當(dāng)中進行while循環(huán),然后不斷的從任務(wù)隊列當(dāng)中獲取任務(wù)函數(shù),然后進行執(zhí)行,直到要求停止線程池當(dāng)中的線程的時候線程再進行退出,整個過程的代碼大致如下所示:

??public?void?run()?{
????while?(!isStopped)?{
??????try?{
????????Runnable?task?=?tasks.take();
????????task.run();
??????}?catch?(InterruptedException?e)?{
????????//?do?nothing
??????}
????}
??}

關(guān)于線程池要有一部分細節(jié)也很重要,比如說我們需要一個并發(fā)安全的阻塞隊列,如何保證所有線程正常退出等等,我們在下篇文章當(dāng)中進行實現(xiàn),而且將仔細分析這里面的細節(jié)。

總結(jié)

在本篇文章當(dāng)中主要給大家介紹了線程到線程池的演化過程,主要介紹線程池實現(xiàn)的基本原理,主要解讀了線程池背后的基本原理,希望大家有所收獲!

以上就是一文帶你深入剖析Java線程池的前世今生的詳細內(nèi)容,更多關(guān)于Java線程池的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于Bigdecimal科學(xué)計數(shù)問題

    基于Bigdecimal科學(xué)計數(shù)問題

    這篇文章主要介紹了基于Bigdecimal科學(xué)計數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • JavaSE中compare、compareTo的區(qū)別

    JavaSE中compare、compareTo的區(qū)別

    本文主要介紹了JavaSE中compare、compareTo的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • spring-boot通過@Scheduled配置定時任務(wù)及定時任務(wù)@Scheduled注解的方法

    spring-boot通過@Scheduled配置定時任務(wù)及定時任務(wù)@Scheduled注解的方法

    這篇文章主要介紹了spring-boot通過@Scheduled配置定時任務(wù),文中還給大家介紹了springboot 定時任務(wù)@Scheduled注解的方法,需要的朋友可以參考下
    2017-11-11
  • java反射之方法反射的基本操作方法

    java反射之方法反射的基本操作方法

    下面小編就為大家?guī)硪黄猨ava反射之方法反射的基本操作方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Java字節(jié)流和字符流及IO流的總結(jié)

    Java字節(jié)流和字符流及IO流的總結(jié)

    本文主要將Java中的IO流進行了梳理,通過將其分成字節(jié)流和字符流,以及輸入流和輸出流分別統(tǒng)計,來建立一個對 Java中IO流全局的概念,通過一些實例來演示了如何通過不同類型的流來組合實現(xiàn)強大靈活的輸入和輸出,最后介紹了同時支持輸入和輸出的 RandomAccessFile。
    2021-04-04
  • logback自定義json日志輸出示例詳解

    logback自定義json日志輸出示例詳解

    這篇文章主要為大家介紹了logback自定義json日志輸出,就是通過logback日志體系以及l(fā)ogstash提供的json?log依賴將數(shù)據(jù)以json格式記錄到日志文件的例子
    2022-03-03
  • 淺析Java隨機數(shù)與定時器

    淺析Java隨機數(shù)與定時器

    本篇文章給大家分析了Java隨機數(shù)與定時器的實現(xiàn)原理以及代碼分享,有需要的讀者參考下吧。
    2018-02-02
  • Spring Cloud動態(tài)配置刷新RefreshScope使用示例詳解

    Spring Cloud動態(tài)配置刷新RefreshScope使用示例詳解

    這篇文章主要為大家介紹了Spring Cloud動態(tài)配置刷新RefreshScope使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • PowerJob的QueryConvertUtils工作流程源碼解讀

    PowerJob的QueryConvertUtils工作流程源碼解讀

    這篇文章主要為大家介紹了PowerJob的QueryConvertUtils工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • JavaWeb實體類轉(zhuǎn)為json對象的實現(xiàn)方法

    JavaWeb實體類轉(zhuǎn)為json對象的實現(xiàn)方法

    這篇文章主要介紹了JavaWeb實體類轉(zhuǎn)為json對象的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評論