最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java之線程池使用與原理全面解析

 更新時(shí)間:2024年03月27日 09:28:21   作者:NingKangMing  
這篇文章主要介紹了Java之線程池使用與原理全面解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

為什么要使用線程池?

JDK1.5后JUC包添加了線程池相關(guān)接口,在Java誕生之初并沒有線程池這個(gè)概念。

剛開始Java程序都是自行創(chuàng)建線程去處理任務(wù)。隨著應(yīng)用使用的線程越來越多,JDK開發(fā)者們發(fā)現(xiàn)有必要使用一個(gè)統(tǒng)一的類來管理這些線程,從而有效提高線程的執(zhí)行效率,減少創(chuàng)建、銷毀線程的開銷。

大量線程的創(chuàng)建、銷毀是非常消耗資源的。創(chuàng)建線程需要消耗一定的內(nèi)存、CPU資源,大量的線程也會(huì)導(dǎo)致大量的線程上下文切換,上下文切換代碼也是相當(dāng)大的,過多的線程導(dǎo)致頻繁切換更是可能使系統(tǒng)性能急速下降。

另外操作系統(tǒng)對(duì)每個(gè)進(jìn)程能創(chuàng)建的線程數(shù)也是有限制的,不可能無限創(chuàng)建。但是大量任務(wù)也不可能只在主線程處理吧,這樣也太慢了。

比如下面的例子,創(chuàng)建上萬的線程,每個(gè)線程打印一下線程名字,觀察一下任務(wù)管理器,CPU直接用完。

這只是簡(jiǎn)單的任務(wù),要是復(fù)雜長(zhǎng)時(shí)間的任務(wù),整個(gè)操作系統(tǒng)可能都會(huì)受到影響(CPU利用率長(zhǎng)時(shí)間下不來,影響其他程序)

public class BadMultiThreadTest {
 
    public static void main(String[] args) {
        Runnable r = () -> {
            System.out.println("ThreadName-" + Thread.currentThread().getName());
        };
        //過多創(chuàng)建線程導(dǎo)致系統(tǒng)資源消耗嚴(yán)重
        for (int i = 0; i < 10000; i++) {
            Thread thread = new Thread(r);
            thread.start();
        }
    }
}

線程池就是為了解決上述問題出現(xiàn)的,解決問題的思路很清晰,就是創(chuàng)建好一定數(shù)量的線程,有任務(wù)來了就用這些線程來執(zhí)行任務(wù),任務(wù)過多把池里面的線程都占用了就放隊(duì)列排隊(duì)等候其他任務(wù)執(zhí)行,一旦有空閑線程就可以從隊(duì)列里面取出任務(wù)并執(zhí)行。

有了可控的線程池,系統(tǒng)就不會(huì)處于一種可能隨時(shí)被大量并發(fā)導(dǎo)致線程大量創(chuàng)建,最終壓跨系統(tǒng)的危險(xiǎn)中。

如何使用線程池?

使用線程池去改造上面的例子:

public class MultiThreadPoolTest {
 
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10000; i++) {
            executorService.execute(() -> {
                System.out.println("ThreadName-" + Thread.currentThread().getName());
            });
        }
    }
}

這次再觀察任務(wù)管理器,這次CPU占用不會(huì)說飆長(zhǎng),而是相對(duì)平穩(wěn)。打印的線程名稱就是在ThreadName-pool-1-thread-1到ThreadName-pool-1-thread-10之間變化,說明這一萬個(gè)任務(wù)都是這10個(gè)線程處理的。 

線程池的參數(shù)含義

上面的例子簡(jiǎn)單的使用了Excutors工具類來創(chuàng)建了一個(gè)固定線程數(shù)的線程池。

這個(gè)工具類還可以創(chuàng)建單線程線程池、可緩存線程池、定時(shí)執(zhí)行任務(wù)的線程池等。

這些線程池的創(chuàng)建事實(shí)上都是在創(chuàng)建一個(gè)ThreadPoolExecutor實(shí)例,只是通過傳遞不同參數(shù),實(shí)現(xiàn)不同的線程池效果而已。

如果我們把里面的參數(shù)都搞明白,我們就可以根據(jù)實(shí)際需求去自定義線程池,實(shí)際開發(fā)中,我們都應(yīng)該使用自定義的線程池去處理相關(guān)業(yè)務(wù),這樣能最大提高線程池使用效率,提高系統(tǒng)性能。當(dāng)然,這還得靠我們對(duì)業(yè)務(wù)的理解,從而定義出合理的線程池。

通過下面這句代碼,跟蹤源碼

Executors.newFixedThreadPool(10);

最終調(diào)用的函數(shù)如下,它包含了線程池的所有參數(shù)注釋:

    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

下面簡(jiǎn)單總結(jié)一下參數(shù)的含義:

參數(shù)名稱含義
corePoolSize核心線程數(shù)
maximumPoolSize最大線程數(shù)
keepAliveTime+時(shí)間單位空閑線程存活時(shí)間
workQueue任務(wù)隊(duì)列
threadFactory創(chuàng)建線程的工廠類
handler被拒絕任務(wù)處理器

線程池處理任務(wù)的流程

看一下下面的流程圖就能清晰知道任務(wù)從被提交再到被線程池中線程執(zhí)行的流程了。

如上流程圖,任務(wù)被提交后,線程池會(huì)檢查核心線程數(shù)是否滿了,如果不是,則會(huì)創(chuàng)建一條核心線程以執(zhí)行該任務(wù)。

如果滿了,則把任務(wù)放到阻塞隊(duì)列中,等待有空閑的核心線程來執(zhí)行任務(wù)。阻塞隊(duì)列如果也滿了,則需要檢查最大核心線程數(shù)是否滿了,如果沒滿,創(chuàng)建非核心線程以執(zhí)行任務(wù),如果滿了,表示線程池再也沒能力去處理該任務(wù)了,則需要拒絕策略做處理。

注意到構(gòu)建線程池的參數(shù)中有keepAliveTime+時(shí)間單位這兩個(gè)參數(shù),這兩個(gè)參數(shù)正是用于回收非核心線程用的,當(dāng)非核心線程沒任務(wù)了,空閑時(shí)間達(dá)到keepAliveTime配置的值后將會(huì)被線程池銷毀以回收一些系統(tǒng)資源。

使用線程池的優(yōu)點(diǎn)

  • 根據(jù)上面可以簡(jiǎn)略總結(jié)出使用線程池的幾點(diǎn)優(yōu)點(diǎn):
  • 解決線程創(chuàng)建、銷毀等生命周期系統(tǒng)消耗過大問題。因?yàn)榫€程池中的線程一旦創(chuàng)建過,核心線程是會(huì)一直駐留在池中待用的,這樣任務(wù)來了后,直接可以執(zhí)行,消除了創(chuàng)建線程的系統(tǒng)開銷。系統(tǒng)響應(yīng)更及時(shí),使用更絲滑。
  • 線程池使得系統(tǒng)可控性更強(qiáng)。它避免了系統(tǒng)資源使用不當(dāng)導(dǎo)致系統(tǒng)崩潰,能更合理的使用CPU和內(nèi)存資源。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java非遞歸實(shí)現(xiàn)之二叉樹的前中后序遍歷詳解

    java非遞歸實(shí)現(xiàn)之二叉樹的前中后序遍歷詳解

    樹的遍歷順序大體分為三種:前序遍歷(先根遍歷、先序遍歷),中序遍歷(中根遍歷),后序遍歷(后根遍歷),本文將給大家詳細(xì)的介紹,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值
    2021-09-09
  • Java如何自定義線程池中隊(duì)列

    Java如何自定義線程池中隊(duì)列

    這篇文章主要介紹了Java如何自定義線程池中隊(duì)列,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • 解決spring boot hibernate 懶加載的問題

    解決spring boot hibernate 懶加載的問題

    這篇文章主要介紹了解決spring boot hibernate 懶加載的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java實(shí)現(xiàn)ATM系統(tǒng)超全面步驟解讀建議收藏

    Java實(shí)現(xiàn)ATM系統(tǒng)超全面步驟解讀建議收藏

    這篇文章主要為大家詳細(xì)介紹了用Java實(shí)現(xiàn)簡(jiǎn)單ATM機(jī)功能,文中實(shí)現(xiàn)流程寫的非常清晰全面,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • springboot如何查找配置文件路徑的順序和其優(yōu)先級(jí)別

    springboot如何查找配置文件路徑的順序和其優(yōu)先級(jí)別

    此文是在工作中遇到的關(guān)于springboot配置文件的問題,在網(wǎng)上查閱資料和自己測(cè)試之后記錄的,以便日后查閱。希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • SpringBoot自定義MessageConverter與內(nèi)容協(xié)商管理器contentNegotiationManager詳解

    SpringBoot自定義MessageConverter與內(nèi)容協(xié)商管理器contentNegotiationManag

    這篇文章主要介紹了SpringBoot自定義MessageConverter與內(nèi)容協(xié)商管理器contentNegotiationManager的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • MyBatisPlus?大數(shù)據(jù)量查詢慢的問題解決

    MyBatisPlus?大數(shù)據(jù)量查詢慢的問題解決

    本文主要介紹了MyBatis?Plus?解決大數(shù)據(jù)量查詢慢問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • java實(shí)現(xiàn)鮮花銷售系統(tǒng)

    java實(shí)現(xiàn)鮮花銷售系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)鮮花銷售系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • SpringBoot使用Atomikos技術(shù)整合多數(shù)據(jù)源的實(shí)現(xiàn)

    SpringBoot使用Atomikos技術(shù)整合多數(shù)據(jù)源的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot使用Atomikos技術(shù)整合多數(shù)據(jù)源的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Spring Boot整合Spring Data Jpa代碼實(shí)例

    Spring Boot整合Spring Data Jpa代碼實(shí)例

    這篇文章主要介紹了Spring Boot整合Spring Data Jpa代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11

最新評(píng)論

西城区| 平凉市| 黔南| 台北市| 平泉县| 嘉定区| 汽车| 茶陵县| 板桥市| 韶关市| 平罗县| 武川县| 桐庐县| 万盛区| 仙桃市| 漾濞| 二连浩特市| 萨嘎县| 临猗县| 陆丰市| 陆川县| 开封市| 汝阳县| 宜春市| 安吉县| 任丘市| 甘洛县| 剑阁县| 朝阳市| 宁明县| 平乐县| 晋江市| 莎车县| 阳谷县| 平乡县| 宜川县| 渝北区| 突泉县| 老河口市| 贺州市| 霍林郭勒市|