欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

手動關(guān)閉

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

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

兩個方法都會中斷線程,用戶可自行判斷是否需要響應中斷。

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

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

自動關(guān)閉

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

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

沒有引用指向且沒有剩余線程的線程池將會自動關(guān)閉。

那么什么情況下線程池中會沒有剩余線程呢?

先來看一下 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 設置為 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ù)的線程,空閑時間一旦達到存活時間,就會被銷毀。
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                           RejectedExecutionHandler handler) { ... ... }

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

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

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

沒錯,這就是線程池自動關(guān)閉的第一種情況。

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

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

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

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

其實Executors.newCachedThrteadPool()創(chuàng)建的線程池,coreP00lSize=0且keepAliveTime=60s,所以也可以自動關(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ù),當線程打印結(jié)束后程序一直不會退出。

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

通過 allowCoreThreadTimeOut 控制核心線程存活時間

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

那你可能要問了,有沒有方法來關(guān)閉核心線程呢?

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

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

接下來,把上面例子修改一下,運行:

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

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

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

線程池中的線程設置為守護線程

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);//設置成守護線程
                    return thread;
                }
            }
);
for (int i = 0; i < 20; i++) {
            executor2.execute(() -> {
               // 簡單地打印當前線程名稱
                System.out.println(Thread.currentThread().getName());
            });
}

雖然corePoolSize>0,而且沒有設置allowCoreThreadTimeOut,但是在創(chuàng)建線程池時通過ThreadFactory指定了線程為守護線程。

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

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

總結(jié)

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

相關(guān)文章

  • MyBatis實現(xiàn)留言板的示例代碼

    MyBatis實現(xiàn)留言板的示例代碼

    本文主要介紹了MyBatis實現(xiàn)留言板的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-08-08
  • SpringMVC異常全局捕獲與錯誤響應的處理方法

    SpringMVC異常全局捕獲與錯誤響應的處理方法

    編程式異常處理是通過在代碼中?顯式編寫異常捕獲邏輯(如?try-catch?塊)來管理異常的方式,開發(fā)者需要手動處理每一個可能拋出異常的代碼段,本文給大家介紹SpringMVC異常全局捕獲與錯誤響應的處理方法,感興趣的朋友一起看看吧
    2025-03-03
  • Java計時新姿勢StopWatch詳解

    Java計時新姿勢StopWatch詳解

    這篇文章主要介紹了Java計時新姿勢StopWatch,最近公司來了個大佬,從他那里學到不少東西,其中一個就是計時的新姿勢「StopWatch」,需要的朋友可以參考下
    2019-07-07
  • java中List集合子類特點淺析

    java中List集合子類特點淺析

    java.util.List接口繼承自Collection接口,是單列集合的一個重要分支,習慣性地會將實現(xiàn)了List接口的對象稱為List集合,下面這篇文章主要給大家介紹了關(guān)于java中List集合子類特點的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-01-01
  • Springboot?引入?Redis?并配置序列化并封裝RedisTemplate?

    Springboot?引入?Redis?并配置序列化并封裝RedisTemplate?

    這篇文章主要介紹了Springboot?引入?Redis?并配置序列化并封裝RedisTemplate。文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • Java8之lambda表達式基本語法

    Java8之lambda表達式基本語法

    本文通過示例大家給大家介紹了java8之lambda表達式的基本語法,感興趣的的朋友一起看看吧
    2017-08-08
  • Java的MybatisPlus詳解

    Java的MybatisPlus詳解

    這篇文章主要介紹了Java的MybatisPlus詳解,MyBatis-Plus是一個 MyBatis的增強工具,在MyBatis的基礎上只做增強不做改變,為簡化開發(fā)、提高效率而生,需要的朋友可以參考下
    2023-07-07
  • Java遠程連接Linux服務器并執(zhí)行命令及上傳文件功能

    Java遠程連接Linux服務器并執(zhí)行命令及上傳文件功能

    這篇文章主要介紹了Java遠程連接Linux服務器并執(zhí)行命令及上傳文件功能,本文是小編整理的代碼筆記,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-05-05
  • SpringDataJPA之Specification復雜查詢實戰(zhàn)

    SpringDataJPA之Specification復雜查詢實戰(zhàn)

    這篇文章主要介紹了SpringDataJPA之Specification復雜查詢實戰(zhàn),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Javafx利用fxml變換場景的實現(xiàn)示例

    Javafx利用fxml變換場景的實現(xiàn)示例

    本文主要介紹了Javafx利用fxml變換場景的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-07-07

最新評論