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

java中線程池的關(guān)閉問(wèn)題

 更新時(shí)間:2023年08月10日 16:41:41   作者:趕路人兒  
這篇文章主要介紹了java中線程池的關(guān)閉問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

java線程池的關(guān)閉問(wèn)題

線程池是一個(gè)重要的資源,關(guān)閉線程池有兩種方式:手動(dòng)和自動(dòng)。接下來(lái)我們一一講解。

手動(dòng)關(guān)閉

線程池有兩個(gè)方法 shutdown()/shutdownNow()用來(lái)關(guān)閉,二者的區(qū)別:

  • shutdown() 執(zhí)行后停止接受新任務(wù),會(huì)把隊(duì)列的任務(wù)執(zhí)行完畢。
  • shutdownNow() 也是停止接受新任務(wù),但會(huì)中斷所有的任務(wù),將線程池狀態(tài)變?yōu)?stop。

兩個(gè)方法都會(huì)中斷線程,用戶可自行判斷是否需要響應(yīng)中斷。

通常,我們可以設(shè)置一個(gè)shutdownHook來(lái)關(guān)閉線程池:

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    try {
        executorService.shutdown();
        while(!executorService.awaitTermination(10,TimeUnit.SECONDS)) {}
    } catch(Exception e) {
    }
}));

自動(dòng)關(guān)閉

首先要了解線程池在什么情況下會(huì)自動(dòng)關(guān)閉。ThreadPoolExecutor 類(lèi)(最常用的線程池實(shí)現(xiàn)類(lèi))的源碼注釋中有這么一句話:

A pool that is no longer referenced in a program and has no remaining threads will be shutdown automatically.

沒(méi)有引用指向且沒(méi)有剩余線程的線程池將會(huì)自動(dòng)關(guān)閉。

那么什么情況下線程池中會(huì)沒(méi)有剩余線程呢?

先來(lái)看一下 ThreadPoolExecutor 參數(shù)最全的構(gòu)造方法:

/**
 * @param corePoolSize the number of threads to keep in the pool, even
 *           if they are idle, unless {@code allowCoreThreadTimeOut} is set
 *        核心線程數(shù):即使是空閑狀態(tài)也可以在線程池存活的線程數(shù)量,除非           
 *        allowCoreThreadTimeOut 設(shè)置為 true。
 * @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.
 *         存活時(shí)間:對(duì)于超出核心線程數(shù)的線程,空閑時(shí)間一旦達(dá)到存活時(shí)間,就會(huì)被銷(xiāo)毀。
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                           RejectedExecutionHandler handler) { ... ... }

這里只關(guān)心與線程存活狀態(tài)最緊密相關(guān)的兩個(gè)參數(shù):corePoolSize和keepAliveTime。

keepAliveTime參數(shù)指定了非核心線程的存活時(shí)間,非核心線程的空閑時(shí)間一旦達(dá)到這個(gè)值,就會(huì)被銷(xiāo)毀,而核心線程則會(huì)繼續(xù)存活,只要有線程存活,線程池也就不會(huì)自動(dòng)關(guān)閉。

聰明的你一定會(huì)想到,如果把corePoolSize設(shè)置為0,再給keepAliveTime指定一個(gè)值的話,那么線程池在空閑一段時(shí)間之后,不就可以自動(dòng)關(guān)閉了嗎?

沒(méi)錯(cuò),這就是線程池自動(dòng)關(guān)閉的第一種情況。

1、自動(dòng)關(guān)閉線程池

核心線程數(shù)為 0 并指定線程存活時(shí)間

ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 5,
                30L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(15));
for (int i = 0; i < 20; i++) {
    executor.execute(() -> {
        // 簡(jiǎn)單地打印當(dāng)前線程名稱
        System.out.println(Thread.currentThread().getName());
    });
}

執(zhí)行上述代碼,當(dāng)線程打印結(jié)束后等待30s,程序退出(代表了線程池自動(dòng)關(guān)閉了)。

其實(shí)Executors.newCachedThrteadPool()創(chuàng)建的線程池,coreP00lSize=0且keepAliveTime=60s,所以也可以自動(dòng)關(guān)閉。

其源碼如下:

public class Executors {
    ... ...
    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
    }
    ... ...
}

如果將上面示例的代碼corePoolSize改成大于0的數(shù),當(dāng)線程打印結(jié)束后程序一直不會(huì)退出。

2、自動(dòng)關(guān)閉線程池

通過(guò) allowCoreThreadTimeOut 控制核心線程存活時(shí)間

將核心線程數(shù)設(shè)置為0雖然可以實(shí)現(xiàn)線程池的自動(dòng)關(guān)閉,但也存在一些弊端,根據(jù)線程池工作原理,當(dāng)corePoolSize=0時(shí)新到來(lái)的任務(wù)會(huì)永遠(yuǎn)優(yōu)先被放入任務(wù)隊(duì)列,然后等待被處理,這顯然會(huì)影響程序的執(zhí)行效率。

那你可能要問(wèn)了,有沒(méi)有方法來(lái)關(guān)閉核心線程呢?

答案是肯定的,從 JDK 1.6 開(kāi)始,ThreadPoolExecutor 類(lèi)新增了一個(gè)allowCoreThreadTimeOut字段,這個(gè)字段值默認(rèn)為false,可使用allowCoreThreadTimeOut()方法對(duì)其進(jìn)行設(shè)置,如果設(shè)置為 true,那么核心線程數(shù)也將受keepAliveTime控制,此方法源碼如下:

public void allowCoreThreadTimeOut(boolean value) {
    // 核心線程存活時(shí)間必須大于0,一旦開(kāi)啟,keepAliveTime 也必須大于0
    if (value && keepAliveTime <= 0)
        throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
    // 將 allowCoreThreadTimeOut 值設(shè)為傳入的參數(shù)值
    if (value != allowCoreThreadTimeOut) {
        allowCoreThreadTimeOut = value;
        // 開(kāi)啟后,清理所有的超時(shí)空閑線程,包括核心線程
        if (value)
            interruptIdleWorkers();
    }
}

接下來(lái),把上面例子修改一下,運(yùn)行:

ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 5,
                30L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(15));
executor.allowCoreThreadTimeOut(true);
for (int i = 0; i < 20; i++) {
            executor.execute(() -> {
               // 簡(jiǎn)單地打印當(dāng)前線程名稱
                System.out.println(Thread.currentThread().getName());
            });
}

 雖然corePoolSize>0,通過(guò)設(shè)置allowCoreThreadTimeOut=true,當(dāng)線程打印結(jié)束后等待30s,程序正常退出(說(shuō)明線程池自動(dòng)關(guān)閉了)

3、自動(dòng)關(guān)閉線程池

線程池中的線程設(shè)置為守護(hù)線程

ThreadPoolExecutor executor2 = new ThreadPoolExecutor(1, 5, 30, TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(150),
            new ThreadFactory() { 
                public Thread newThread(Runnable r) {
                    Thread thread = new Thread(r, r.hashCode()+"");
                    thread.setDaemon(true);//設(shè)置成守護(hù)線程
                    return thread;
                }
            }
);
for (int i = 0; i < 20; i++) {
            executor2.execute(() -> {
               // 簡(jiǎn)單地打印當(dāng)前線程名稱
                System.out.println(Thread.currentThread().getName());
            });
}

雖然corePoolSize>0,而且沒(méi)有設(shè)置allowCoreThreadTimeOut,但是在創(chuàng)建線程池時(shí)通過(guò)ThreadFactory指定了線程為守護(hù)線程。

當(dāng)線程打印結(jié)束后,無(wú)需等待程序正常退出(說(shuō)明線程池自動(dòng)關(guān)閉了)。

當(dāng)然,這里是在main函數(shù)中執(zhí)行,不存在其他非守護(hù)線程哈。

總結(jié)

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

相關(guān)文章

  • Java 面試題基礎(chǔ)知識(shí)集錦

    Java 面試題基礎(chǔ)知識(shí)集錦

    本文主要介紹Java基礎(chǔ)面試題集錦,這里整理了面試java工程師的基礎(chǔ)知識(shí)題錦,有需要的小伙伴可以參考下
    2016-09-09
  • SpringBoot中如何使用Assert進(jìn)行斷言校驗(yàn)

    SpringBoot中如何使用Assert進(jìn)行斷言校驗(yàn)

    Java?提供了內(nèi)置的?assert?機(jī)制,而?Spring?框架也提供了更強(qiáng)大的?Assert?工具類(lèi)來(lái)幫助開(kāi)發(fā)者進(jìn)行參數(shù)校驗(yàn)和狀態(tài)檢查,下面我們就來(lái)看看SpringBoot中如何使用Assert進(jìn)行斷言校驗(yàn)吧
    2025-07-07
  • Atomikos + MybatisPlus解決多數(shù)據(jù)源事務(wù)一致性問(wèn)題解決

    Atomikos + MybatisPlus解決多數(shù)據(jù)源事務(wù)一致性問(wèn)題解決

    在實(shí)際項(xiàng)目的開(kāi)發(fā)過(guò)程中,我們經(jīng)常會(huì)遇到在同一個(gè)項(xiàng)目或微服務(wù)中牽涉到使用兩個(gè)或多個(gè)數(shù)據(jù)源的,本文主要介紹了Atomikos + MybatisPlus解決多數(shù)據(jù)源事務(wù)一致性問(wèn)題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • Java實(shí)現(xiàn)FTP批量大文件上傳下載篇1

    Java實(shí)現(xiàn)FTP批量大文件上傳下載篇1

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)FTP批量大文件上傳下載的基礎(chǔ)篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Java實(shí)現(xiàn)十進(jìn)制與二進(jìn)制互轉(zhuǎn)的示例詳解

    Java實(shí)現(xiàn)十進(jìn)制與二進(jìn)制互轉(zhuǎn)的示例詳解

    這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)十進(jìn)制與二進(jìn)制的互轉(zhuǎn),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下
    2022-11-11
  • Spring?Cloud?Ribbon?負(fù)載均衡使用策略示例詳解

    Spring?Cloud?Ribbon?負(fù)載均衡使用策略示例詳解

    Spring?Cloud?Ribbon?是基于Netflix?Ribbon?實(shí)現(xiàn)的一套客戶端負(fù)載均衡工具,Ribbon客戶端組件提供了一系列的完善的配置,如超時(shí),重試等,這篇文章主要介紹了Spring?Cloud?Ribbon?負(fù)載均衡使用策略示例詳解,需要的朋友可以參考下
    2023-03-03
  • 如何使用Jackson和JSON Pointer查詢解析任何JSON節(jié)點(diǎn)

    如何使用Jackson和JSON Pointer查詢解析任何JSON節(jié)點(diǎn)

    本文介紹了JSON Pointer是字符串表達(dá)式,可以非常方便解析復(fù)雜JSON節(jié)點(diǎn)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java圖片和文本同時(shí)提交到表單的實(shí)例代碼

    java圖片和文本同時(shí)提交到表單的實(shí)例代碼

    在本篇文章里小編給大家整理的是關(guān)于java實(shí)現(xiàn)圖片和文本同時(shí)提交到表單的相關(guān)內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2020-02-02
  • mybatis-plus 處理大數(shù)據(jù)插入太慢的解決

    mybatis-plus 處理大數(shù)據(jù)插入太慢的解決

    這篇文章主要介紹了mybatis-plus 處理大數(shù)據(jù)插入太慢的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Spring?Boot分離配置文件的多種方式總結(jié)

    Spring?Boot分離配置文件的多種方式總結(jié)

    Spring Boot可以外部化程序配置,以便可以在不同環(huán)境中使用相同的應(yīng)用程序代碼;當(dāng)然Spring Boot可以將配置文件進(jìn)行拆分,以便于激活不同的運(yùn)行環(huán)境,下面這篇文章主要給大家總結(jié)介紹了關(guān)于Spring?Boot分離配置文件的多種方式,需要的朋友可以參考下
    2022-11-11

最新評(píng)論

嘉定区| 奈曼旗| 东安县| 双辽市| 南澳县| 文山县| 万山特区| 凤山市| 乐至县| 武隆县| 新沂市| 宁城县| 奎屯市| 青阳县| 阿合奇县| 博湖县| 盐津县| 仙游县| 河津市| 永福县| 松原市| 孝义市| 西乌珠穆沁旗| 股票| 五家渠市| 阿尔山市| 理塘县| 车致| 民勤县| 合川市| 阿拉善左旗| 北流市| 靖宇县| 文水县| 开封县| 鹤山市| 呼玛县| 柳河县| 营口市| 眉山市| 普兰店市|