91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot為異步任務規劃自定義線程池如何實現

發布時間:2022-06-14 11:51:43 來源:億速云 閱讀:209 作者:iii 欄目:開發技術

本篇內容主要講解“springboot為異步任務規劃自定義線程池如何實現”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“springboot為異步任務規劃自定義線程池如何實現”吧!

一、Spring Boot任務線程池

線程池的作用

  • 防止資源占用無限的擴張

  • 調用過程省去資源的創建和銷毀所占用的時間

在高并發環境下,不斷的分配新資源,可能導致系統資源耗盡。所以為了避免這個問題,我們為異步任務規劃一個線程池。當然,如果沒有配置線程池的話,springboot會自動配置一個ThreadPoolTaskExecutor 線程池到bean當中。

# 核心線程數
spring.task.execution.pool.core-size=8  
# 最大線程數
spring.task.execution.pool.max-size=16
# 空閑線程存活時間
spring.task.execution.pool.keep-alive=60s
# 是否允許核心線程超時
spring.task.execution.pool.allow-core-thread-timeout=true
# 線程隊列數量
spring.task.execution.pool.queue-capacity=100
# 線程關閉等待
spring.task.execution.shutdown.await-termination=false
spring.task.execution.shutdown.await-termination-period=
# 線程名稱前綴
spring.task.execution.thread-name-prefix=task-

在springboot配置文件中加入上面的配置,即可實現ThreadPoolTaskExecutor 線程池。

二、自定義線程池

有的時候,我們希望將系統內的一類任務放到一個線程池,另一類任務放到另外一個線程池,所以使用Spring Boot自帶的任務線程池就捉襟見肘了。下面介紹自定義線程池的方法。

創建一個 線程池配置類 TaskConfiguration ,并配置一個 任務線程池對象 taskExecutor。

@Configuration
public class TaskConfiguration {
    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("taskExecutor-");
        executor.setRejectedExecutionHandler(new CallerRunsPolicy());
        return executor;
    }
}

springboot為異步任務規劃自定義線程池如何實現

上面我們通過使用 ThreadPoolTaskExecutor 創建了一個 線程池,同時設置了以下這些參數:

線程池屬性屬性的作用上文代碼設置初始值
核心線程數CorePoolSize線程池創建時候初始化的線程數,最小線程數10
最大線程數MaxPoolSize線程池最大的線程數,只有在緩沖隊列滿了之后,才會申請超過核心線程數的線程20
緩沖任務隊列QueueCapacity用來緩沖執行任務的隊列200
允許線程的空閑時間KeepAliveSeconds超過了核心線程之外的線程,在空閑時間到達之后,沒活干的線程會被銷毀60秒
線程池名的前綴 ThreadNamePrefix可以用于定位處理任務所在的線程池taskExecutor-
線程池對任務的Reject策略RejectedExecutionHandler當線程池運行飽和,或者線程池處于shutdown臨界狀態時,用來拒絕一個任務的執行CallerRunsPolicy

Reject策略預定義有四種:

  • AbortPolicy,用于被拒絕任務的處理程序,它將拋出RejectedExecutionException。

  • CallerRunsPolicy,用于被拒絕任務的處理程序,它直接在execute方法的調用線程中運行被拒絕的任務。

  • DiscardOldestPolicy,用于被拒絕任務的處理程序,它放棄最舊的未處理請求,然后重試execute。

  • DiscardPolicy,用于被拒絕任務的處理程序,默認情況下它將丟棄被拒絕的任務。

創建 AsyncExecutorTask類,三個任務的配置和 AsyncTask 一樣,不同的是 @Async 注解需要指定前面配置的 線程池的名稱 taskExecutor。

@Component
public class AsyncExecutorTask extends AbstractTask {
    @Async("taskExecutor")
    public Future<String> doTaskOneCallback() throws Exception {
        super.doTaskOne();
        System.out.println("任務一,當前線程:" + Thread.currentThread().getName());
        return new AsyncResult<>("任務一完成");
    }

    @Async("taskExecutor")
    public Future<String> doTaskTwoCallback() throws Exception {
        super.doTaskTwo();
        System.out.println("任務二,當前線程:" + Thread.currentThread().getName());
        return new AsyncResult<>("任務二完成");
    }

    @Async("taskExecutor")
    public Future<String> doTaskThreeCallback() throws Exception {
        super.doTaskThree();
        System.out.println("任務三,當前線程:" + Thread.currentThread().getName());
        return new AsyncResult<>("任務三完成");
    }
}

在 單元測試 用例中,注入 AsyncExecutorTask 對象,并在測試用例中執行 doTaskOne(),doTaskTwo(),doTaskThree() 三個方法。

@SpringBootTest
public class AsyncExecutorTaskTest {
    @Autowired
    private AsyncExecutorTask task;

    @Test
    public void testAsyncExecutorTask() throws Exception {
        task.doTaskOneCallback();
        task.doTaskTwoCallback();
        task.doTaskThreeCallback();

        sleep(30 * 1000L);
    }
}

執行一下上述的 單元測試,可以看到如下結果:

開始做任務一
開始做任務三
開始做任務二
完成任務二,耗時:3905毫秒
任務二,當前線程:taskExecutor-2
完成任務一,耗時:6184毫秒
任務一,當前線程:taskExecutor-1
完成任務三,耗時:9737毫秒
任務三,當前線程:taskExecutor-3

執行上面的單元測試,觀察到 任務線程池 的 線程池名的前綴 被打印,說明 線程池 成功執行 異步任務!

三、優雅地關閉線程池

由于在應用關閉的時候異步任務還在執行,導致類似 數據庫連接池 這樣的對象一并被 銷毀了,當 異步任務 中對 數據庫 進行操作就會出錯。

解決方案如下,重新設置線程池配置對象,新增線程池 setWaitForTasksToCompleteOnShutdown() 和 setAwaitTerminationSeconds() 配置:

@Bean("taskExecutor")
public Executor taskExecutor() {
    ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
    executor.setPoolSize(20);
    executor.setThreadNamePrefix("taskExecutor-");
    executor.setWaitForTasksToCompleteOnShutdown(true);
    executor.setAwaitTerminationSeconds(60);
    return executor;
}
  • setWaitForTasksToCompleteOnShutdown(true): 該方法用來設置 線程池關閉 的時候 等待 所有任務都完成后,再繼續 銷毀 其他的 Bean,這樣這些 異步任務 的 銷毀 就會先于 數據庫連接池對象 的銷毀。

  • setAwaitTerminationSeconds(60): 該方法用來設置線程池中 任務的等待時間,如果超過這個時間還沒有銷毀就 強制銷毀,以確保應用最后能夠被關閉,而不是阻塞住。

異步任務** 的 銷毀 就會先于 數據庫連接池對象 的銷毀。

  • setAwaitTerminationSeconds(60): 該方法用來設置線程池中 任務的等待時間,如果超過這個時間還沒有銷毀就 強制銷毀,以確保應用最后能夠被關閉,而不是阻塞住。

到此,相信大家對“springboot為異步任務規劃自定義線程池如何實現”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

乃东县| 鄂尔多斯市| 永城市| 互助| 嘉祥县| 永丰县| 安达市| 定日县| 临武县| 朝阳县| 雅江县| 本溪市| 灌阳县| 攀枝花市| 朔州市| 汝城县| 定边县| 江源县| 永新县| 孟州市| 巨野县| 宁津县| 田东县| 恩施市| 镇平县| 江都市| 石家庄市| 桃园县| 林芝县| 东山县| 绥滨县| 和田市| 宜宾县| 长海县| 乐都县| 上虞市| 班戈县| 上栗县| 工布江达县| 九台市| 松潘县|