一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何正確使用SpringBoot中的線程池

Android編程精選 ? 來源:CSDN博客 ? 作者:如漩渦 ? 2021-09-02 17:14 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

來自丨CSDN

https://blog.csdn.net/m0_37701381/article/details/81072774

使用步驟

先創(chuàng)建一個(gè)線程池的配置,讓Spring Boot加載,用來定義如何創(chuàng)建一個(gè)ThreadPoolTaskExecutor,要使用@Configuration和@EnableAsync這兩個(gè)注解,表示這是個(gè)配置類,并且是線程池的配置類

@Configuration@EnableAsyncpublic class ExecutorConfig {

private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);

@Value(“${async.executor.thread.core_pool_size}”)

private int corePoolSize;

@Value(“${async.executor.thread.max_pool_size}”)

private int maxPoolSize;

@Value(“${async.executor.thread.queue_capacity}”)

private int queueCapacity;

@Value(“${async.executor.thread.name.prefix}”)

private String namePrefix;

@Bean(name = “asyncServiceExecutor”)

public Executor asyncServiceExecutor() {

logger.info(“start asyncServiceExecutor”);

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

//配置核心線程數(shù)

executor.setCorePoolSize(corePoolSize);

//配置最大線程數(shù)

executor.setMaxPoolSize(maxPoolSize);

//配置隊(duì)列大小

executor.setQueueCapacity(queueCapacity);

//配置線程池中的線程的名稱前綴

executor.setThreadNamePrefix(namePrefix);

// rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù)

// CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來執(zhí)行

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

//執(zhí)行初始化

executor.initialize();

return executor;

}

}

@Value是我配置在application.properties,可以參考配置,自由定義

# 異步線程配置# 配置核心線程數(shù)

async.executor.thread.core_pool_size = 5

# 配置最大線程數(shù)

async.executor.thread.max_pool_size = 5

# 配置隊(duì)列大小

async.executor.thread.queue_capacity = 99999

# 配置線程池中的線程的名稱前綴

async.executor.thread.name.prefix = async-service-

創(chuàng)建一個(gè)Service接口,是異步線程的接口

public interface AsyncService {

/**

* 執(zhí)行異步任務(wù)

* 可以根據(jù)需求,自己加參數(shù)擬定,我這里就做個(gè)測(cè)試演示

*/

void executeAsync();

}

實(shí)現(xiàn)類

@Servicepublic class AsyncServiceImpl implements AsyncService {

private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);

@Override

@Async(“asyncServiceExecutor”)

public void executeAsync() {

logger.info(“start executeAsync”);

System.out.println(“異步線程要做的事情”);

System.out.println(“可以在這里執(zhí)行批量插入等耗時(shí)的事情”);

logger.info(“end executeAsync”);

}

}

將Service層的服務(wù)異步化,在executeAsync()方法上增加注解@Async(“asyncServiceExecutor”),asyncServiceExecutor方法是前面ExecutorConfig.java中的方法名,表明executeAsync方法進(jìn)入的線程池是asyncServiceExecutor方法創(chuàng)建的。

接下來就是在Controller里或者是哪里通過注解@Autowired注入這個(gè)Service

@Autowiredprivate AsyncService asyncService;

@GetMapping(“/async”)

public void async(){

asyncService.executeAsync();

}

用postmain或者其他工具來多次測(cè)試請(qǐng)求一下

2018-07-16 2247.655 INFO 10516 --- [async-service-5] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2247.655 INFO 10516 --- [async-service-5] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

2018-07-16 2247.770 INFO 10516 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2247.770 INFO 10516 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

2018-07-16 2247.816 INFO 10516 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2247.816 INFO 10516 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

2018-07-16 2248.833 INFO 10516 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2248.834 INFO 10516 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

2018-07-16 2248.986 INFO 10516 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2248.987 INFO 10516 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

通過以上日志可以發(fā)現(xiàn),[async-service-]是有多個(gè)線程的,顯然已經(jīng)在我們配置的線程池中執(zhí)行了,并且每次請(qǐng)求中,controller的起始和結(jié)束日志都是連續(xù)打印的,表明每次請(qǐng)求都快速響應(yīng)了,而耗時(shí)的操作都留給線程池中的線程去異步執(zhí)行;

雖然我們已經(jīng)用上了線程池,但是還不清楚線程池當(dāng)時(shí)的情況,有多少線程在執(zhí)行,多少在隊(duì)列中等待呢?這里我創(chuàng)建了一個(gè)ThreadPoolTaskExecutor的子類,在每次提交線程的時(shí)候都會(huì)將當(dāng)前線程池的運(yùn)行狀況打印出來

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import org.springframework.util.concurrent.ListenableFuture;

import java.util.concurrent.Callable;

import java.util.concurrent.Future;

import java.util.concurrent.ThreadPoolExecutor;

/**

* @Author: ChenBin

*/public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {

private static final Logger logger = LoggerFactory.getLogger(VisiableThreadPoolTaskExecutor.class);

private void showThreadPoolInfo(String prefix) {

ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();

if (null == threadPoolExecutor) {

return;

}

logger.info(“{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]”,

this.getThreadNamePrefix(),

prefix,

threadPoolExecutor.getTaskCount(),

threadPoolExecutor.getCompletedTaskCount(),

threadPoolExecutor.getActiveCount(),

threadPoolExecutor.getQueue().size());

}

@Override

public void execute(Runnable task) {

showThreadPoolInfo(“1. do execute”);

super.execute(task);

}

@Override

public void execute(Runnable task, long startTimeout) {

showThreadPoolInfo(“2. do execute”);

super.execute(task, startTimeout);

}

@Override

public Future《?》 submit(Runnable task) {

showThreadPoolInfo(“1. do submit”);

return super.submit(task);

}

@Override

public 《T》 Future《T》 submit(Callable《T》 task) {

showThreadPoolInfo(“2. do submit”);

return super.submit(task);

}

@Override

public ListenableFuture《?》 submitListenable(Runnable task) {

showThreadPoolInfo(“1. do submitListenable”);

return super.submitListenable(task);

}

@Override

public 《T》 ListenableFuture《T》 submitListenable(Callable《T》 task) {

showThreadPoolInfo(“2. do submitListenable”);

return super.submitListenable(task);

}

}

如上所示,showThreadPoolInfo方法中將任務(wù)總數(shù)、已完成數(shù)、活躍線程數(shù),隊(duì)列大小都打印出來了,然后Override了父類的execute、submit等方法,在里面調(diào)用showThreadPoolInfo方法,這樣每次有任務(wù)被提交到線程池的時(shí)候,都會(huì)將當(dāng)前線程池的基本情況打印到日志中;

修改ExecutorConfig.java的asyncServiceExecutor方法,將ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor()改為ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor()

@Bean(name = “asyncServiceExecutor”)

public Executor asyncServiceExecutor() {

logger.info(“start asyncServiceExecutor”);

//在這里修改

ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();

//配置核心線程數(shù)

executor.setCorePoolSize(corePoolSize);

//配置最大線程數(shù)

executor.setMaxPoolSize(maxPoolSize);

//配置隊(duì)列大小

executor.setQueueCapacity(queueCapacity);

//配置線程池中的線程的名稱前綴

executor.setThreadNamePrefix(namePrefix);

// rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù)

// CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來執(zhí)行

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

//執(zhí)行初始化

executor.initialize();

return executor;

}

再次啟動(dòng)該工程測(cè)試

2018-07-16 2230.951 INFO 14088 --- [nio-8087-exec-2] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [0], completedTaskCount [0], activeCount [0], queueSize [0]

2018-07-16 2230.952 INFO 14088 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2230.953 INFO 14088 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

2018-07-16 2231.351 INFO 14088 --- [nio-8087-exec-3] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [1], completedTaskCount [1], activeCount [0], queueSize [0]

2018-07-16 2231.353 INFO 14088 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2231.353 INFO 14088 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

2018-07-16 2231.927 INFO 14088 --- [nio-8087-exec-5] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [2], completedTaskCount [2], activeCount [0], queueSize [0]

2018-07-16 2231.929 INFO 14088 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2231.930 INFO 14088 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

2018-07-16 2232.496 INFO 14088 --- [nio-8087-exec-7] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [3], completedTaskCount [3], activeCount [0], queueSize [0]

2018-07-16 2232.498 INFO 14088 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync

異步線程要做的事情

可以在這里執(zhí)行批量插入等耗時(shí)的事情

2018-07-16 2232.499 INFO 14088 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync

注意這一行日志:

2018-07-16 2232.496 INFO 14088 --- [nio-8087-exec-7] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [3], completedTaskCount [3], activeCount [0], queueSize [0]

這說明提交任務(wù)到線程池的時(shí)候,調(diào)用的是submit(Callable task)這個(gè)方法,當(dāng)前已經(jīng)提交了3個(gè)任務(wù),完成了3個(gè),當(dāng)前有0個(gè)線程在處理任務(wù),還剩0個(gè)任務(wù)在隊(duì)列中等待,線程池的基本情況一路了然;

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14964
  • 線程池
    +關(guān)注

    關(guān)注

    0

    文章

    57

    瀏覽量

    7108
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    175

    瀏覽量

    359

原文標(biāo)題:SpringBoot中的線程池,你真的會(huì)用么?

文章出處:【微信號(hào):AndroidPush,微信公眾號(hào):Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    線程的安全注意事項(xiàng)

    線程安全是指多個(gè)線程同時(shí)訪問或修改共享資源時(shí),能夠保證程序的正確性和可靠性。 開發(fā)者選擇TaskPool或Worker進(jìn)行多線程開發(fā)時(shí),在TaskPool和Worker的工作
    發(fā)表于 06-20 07:49

    socket 多線程編程實(shí)現(xiàn)方法

    在現(xiàn)代網(wǎng)絡(luò)編程,多線程技術(shù)被廣泛應(yīng)用于提高服務(wù)器的并發(fā)處理能力。Socket編程是網(wǎng)絡(luò)通信的基礎(chǔ),而將多線程技術(shù)應(yīng)用于Socket編程,可以顯著提升服務(wù)器的性能。 多線程編程的基本概
    的頭像 發(fā)表于 11-12 14:16 ?957次閱讀

    的無線測(cè)溫在線監(jiān)測(cè)系統(tǒng)

    今天分享的酒廠窖的無線測(cè)溫系統(tǒng),包含硬件和軟件為一體的標(biāo)準(zhǔn)解決方案。 行業(yè)背景 說到窖的測(cè)溫,不得不從酒廠的酒廠的發(fā)酵說起。酒廠發(fā)酵是指用于生產(chǎn)釀酒的一種設(shè)備,通常由不銹鋼或玻
    的頭像 發(fā)表于 10-28 09:52 ?388次閱讀
    窖<b class='flag-5'>池</b>的無線測(cè)溫在線監(jiān)測(cè)系統(tǒng)

    怎么在JAVA確定線性大小

    在JAVA確定線性大小,分別介紹CPU密集型任務(wù)和I/O密集型任務(wù)及其處理方法。
    的頭像 發(fā)表于 10-24 14:02 ?444次閱讀

    Python線程和多進(jìn)程的區(qū)別

    Python作為一種高級(jí)編程語言,提供了多種并發(fā)編程的方式,其中多線程與多進(jìn)程是最常見的兩種方式之一。在本文中,我們將探討Python線程與多進(jìn)程的概念、區(qū)別以及如何使用線程
    的頭像 發(fā)表于 10-23 11:48 ?966次閱讀
    Python<b class='flag-5'>中</b>多<b class='flag-5'>線程</b>和多進(jìn)程的區(qū)別

    離心溫度監(jiān)測(cè)物聯(lián)網(wǎng)系統(tǒng)方案

    在現(xiàn)有技術(shù)的鋼丸生產(chǎn)工藝,一般采用離心法實(shí)現(xiàn)鋼丸的成形,其原理是將熔融狀態(tài)的鋼水裝入離心機(jī),通過離心力將鋼水甩出離心機(jī),離心機(jī)位于一個(gè)冷卻的中部,因此從離心機(jī)甩出的鋼水落入冷卻
    的頭像 發(fā)表于 09-20 10:56 ?356次閱讀
    離心<b class='flag-5'>池</b>溫度監(jiān)測(cè)物聯(lián)網(wǎng)系統(tǒng)方案

    買藥秒送 JADE動(dòng)態(tài)線程實(shí)踐及原理淺析

    一、背景及JADE介紹 買藥秒送是健康即時(shí)零售業(yè)務(wù)新的核心流量場(chǎng)域,面對(duì)京東首頁高流量曝光,我們對(duì)頻道頁整個(gè)技術(shù)架構(gòu)方案進(jìn)行升級(jí),保障接口高性能、系統(tǒng)高可用。 動(dòng)態(tài)線程是買藥頻道應(yīng)用的技術(shù)之一
    的頭像 發(fā)表于 09-04 11:11 ?1150次閱讀
    買藥秒送 JADE動(dòng)態(tài)<b class='flag-5'>線程</b><b class='flag-5'>池</b>實(shí)踐及原理淺析

    CPU線程和程序線程的區(qū)別

    CPU的線程與程序的線程在概念、作用、實(shí)現(xiàn)方式以及性能影響等方面存在顯著差異。以下是對(duì)兩者區(qū)別的詳細(xì)闡述,旨在深入探討這一技術(shù)話題。
    的頭像 發(fā)表于 09-02 11:18 ?2033次閱讀

    高壓放大器在鐵磁鐵電異質(zhì)結(jié)系統(tǒng)物理儲(chǔ)備計(jì)算的應(yīng)用

    實(shí)驗(yàn)名稱:高壓放大器在鐵磁鐵電異質(zhì)結(jié)系統(tǒng)物理儲(chǔ)備計(jì)算的應(yīng)用實(shí)驗(yàn)內(nèi)容:將信號(hào)發(fā)生器產(chǎn)生的一段任意波形經(jīng)高壓放大器放大后輸入到系統(tǒng),探測(cè)系統(tǒng)的實(shí)時(shí)輸出,并對(duì)該系統(tǒng)進(jìn)行儲(chǔ)備計(jì)算的模型
    的頭像 發(fā)表于 08-23 13:49 ?557次閱讀
    高壓放大器在鐵磁鐵電異質(zhì)結(jié)系統(tǒng)物理儲(chǔ)備<b class='flag-5'>池</b>計(jì)算<b class='flag-5'>中</b>的應(yīng)用

    基于OpenHarmony標(biāo)準(zhǔn)系統(tǒng)的C++公共基礎(chǔ)類庫案例:ThreadPoll

    、線程增強(qiáng)及線程等接口 安全數(shù)據(jù)容器、數(shù)據(jù)序列化等接口 各子系統(tǒng)的錯(cuò)誤碼相關(guān)定義 2.1、添加C++公共基礎(chǔ)類庫依賴 修改需調(diào)用模塊的BUILD.gn,在external_deps或deps
    發(fā)表于 08-12 11:42

    一文掌握Python多線程

    使用線程可以把占據(jù)長(zhǎng)時(shí)間的程序的任務(wù)放到后臺(tái)去處理。
    的頭像 發(fā)表于 08-05 15:46 ?1224次閱讀

    RTOS SDK正確設(shè)置PWM負(fù)載怎么解決?

    (..);pwm_start() 工作正常, 但是當(dāng)使用時(shí): setduty(..);pwm_start() setduty(..);pwm_start() PWM 行為不正確。 作為 setduty(..);pwm_start() 可以來自不同的線程、中斷。
    發(fā)表于 07-18 07:09

    神經(jīng)網(wǎng)絡(luò)的卷積層、化層與全連接層

    在深度學(xué)習(xí),卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network, CNN)是一種特別適用于處理圖像數(shù)據(jù)的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。它通過卷積層、化層和全連接層的組合,實(shí)現(xiàn)了對(duì)圖像特征的自動(dòng)提取和分類。本文將詳細(xì)探討卷積層、
    的頭像 發(fā)表于 07-11 14:18 ?9877次閱讀

    卷積神經(jīng)網(wǎng)絡(luò)化層的作用

    。其中,化層(Pooling Layer)作為CNN的重要組成部分,在降低模型復(fù)雜度、提高計(jì)算效率以及增強(qiáng)模型的不變性和魯棒性方面發(fā)揮著關(guān)鍵作用。本文將從多個(gè)方面深入探討化層的作用,力求全面解析其在CNN的核心地位。
    的頭像 發(fā)表于 07-03 15:58 ?3239次閱讀

    卷積神經(jīng)網(wǎng)絡(luò)cnn化層的主要作用

    卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)是深度學(xué)習(xí)領(lǐng)域中一種重要的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu),廣泛應(yīng)用于圖像識(shí)別、語音識(shí)別、自然語言處理等領(lǐng)域。在CNN,化層
    的頭像 發(fā)表于 07-02 14:50 ?2432次閱讀