91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

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

完善資料讓更多小伙伴認(rèn)識你,還能領(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)建一個線程池的配置,讓Spring Boot加載,用來定義如何創(chuàng)建一個ThreadPoolTaskExecutor,要使用@Configuration和@EnableAsync這兩個注解,表示這是個配置類,并且是線程池的配置類

@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的時候,如何處理新任務(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)建一個Service接口,是異步線程的接口

public interface AsyncService {

/**

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

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

*/

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í)行批量插入等耗時的事情”);

logger.info(“end executeAsync”);

}

}

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

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

@Autowiredprivate AsyncService asyncService;

@GetMapping(“/async”)

public void async(){

asyncService.executeAsync();

}

用postmain或者其他工具來多次測試請求一下

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

異步線程要做的事情

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

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í)行批量插入等耗時的事情

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í)行批量插入等耗時的事情

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í)行批量插入等耗時的事情

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í)行批量插入等耗時的事情

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

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

雖然我們已經(jīng)用上了線程池,但是還不清楚線程池當(dāng)時的情況,有多少線程在執(zhí)行,多少在隊(duì)列中等待呢?這里我創(chuàng)建了一個ThreadPoolTaskExecutor的子類,在每次提交線程的時候都會將當(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ù)被提交到線程池的時候,都會將當(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的時候,如何處理新任務(wù)

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

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

//執(zhí)行初始化

executor.initialize();

return executor;

}

再次啟動該工程測試

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í)行批量插入等耗時的事情

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í)行批量插入等耗時的事情

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í)行批量插入等耗時的事情

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í)行批量插入等耗時的事情

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

責(zé)任編輯:haq

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

    關(guān)注

    0

    文章

    341

    瀏覽量

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

    關(guān)注

    0

    文章

    58

    瀏覽量

    7388
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    177

    瀏覽量

    684

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

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

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

掃碼添加小助手

加入工程師交流群

    評論

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

    解析Linux的進(jìn)程、線程和協(xié)程

    允許在單個線程內(nèi)實(shí)現(xiàn)多個協(xié)程的并發(fā)執(zhí)行。協(xié)程在執(zhí)行過程可以主動掛起和恢復(fù),這使得編寫高效的異步代碼變得更加容易。協(xié)程通常用于處理I/O密集型任務(wù),能夠提高程序的響應(yīng)性能。 協(xié)程的特點(diǎn)包括: (1
    發(fā)表于 12-22 11:00

    開放協(xié)作,共筑生態(tài)——思爾芯參與上海開放處理器產(chǎn)業(yè)創(chuàng)新中心開業(yè)儀式暨RISC-V專利聯(lián)盟專利儀式

    企業(yè)之一,由總裁林鎧鵬代表公司參加入簽約儀式,將指定專利納入專利,標(biāo)志著思爾芯在共建開放、安全、協(xié)同的RISC-V生態(tài)邁出新的一步。上海開放處理器產(chǎn)業(yè)創(chuàng)新
    的頭像 發(fā)表于 12-15 17:38 ?1149次閱讀
    開放協(xié)作,共筑生態(tài)——思爾芯參與上海開放處理器產(chǎn)業(yè)創(chuàng)新中心開業(yè)儀式暨RISC-V專利聯(lián)盟專利<b class='flag-5'>池</b>入<b class='flag-5'>池</b>儀式

    C語言內(nèi)存使用

    C語言的內(nèi)存管理,從來都是一個讓人頭禿的問題。要想更自由地管理內(nèi)存,就必須去堆申請,然后還需要考慮何時釋放,萬一釋放不當(dāng),或者沒有及時釋放,造成的后果都是難以估量的。 當(dāng)然如果就這些,那倒也還不
    發(fā)表于 12-11 07:57

    線程的系統(tǒng)

    線程系統(tǒng)的事件響應(yīng)也是在中斷完成的,但事件的處理是在線程完成的。在多線程系統(tǒng),
    發(fā)表于 12-08 07:55

    Linux多線程對比單線程的優(yōu)勢

    在Linux系統(tǒng)線程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。線程被包含在進(jìn)程之中,是進(jìn)程的實(shí)際運(yùn)行單位。一個進(jìn)程可以擁有多個線程,這些
    發(fā)表于 12-01 06:11

    如何使用SpringBoot、Vue2.0、MySQL開發(fā)一套云診所系統(tǒng)?

    ? 如何使用Java語言;前端框架:Vue2.0;后端框架:SpringBoot;數(shù) 據(jù) 庫: MySQL 這些技術(shù)開發(fā)一套云診所系統(tǒng)? 技術(shù)棧分析: 后端:SpringBoot
    的頭像 發(fā)表于 11-27 16:02 ?283次閱讀
    如何使用<b class='flag-5'>SpringBoot</b>、Vue2.0、MySQL開發(fā)一套云診所系統(tǒng)?

    高壓放大器在鐵磁鐵電異質(zhì)結(jié)儲備計算的前沿探索

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

    數(shù)據(jù)全復(fù)用高性能化層設(shè)計思路分享

    大家好,本團(tuán)隊(duì)此次分享的內(nèi)容為可實(shí)現(xiàn)數(shù)據(jù)全復(fù)用高性能化層設(shè)計思路,核心部分主要由以下3個部分組成; 1.SRAM讀取模塊;——化使用的存儲為SRAM 基于SRAM讀與寫時序,約束化模塊讀與寫
    發(fā)表于 10-29 07:10

    rtt建兩個線程a和b,怎么確保線程a執(zhí)行完立刻切到線程b?

    怎么獲取從線程開始切換到切換完成用的總的CPU時鐘節(jié)拍數(shù)量?
    發(fā)表于 10-10 06:37

    線程刪除時遇到斷言,是什么原因?qū)е碌模?/a>

    在一個線程調(diào)用線程刪除函數(shù)刪除另外一個線程,這2個線程的優(yōu)先級是相等的,被刪除的線程也是動態(tài)創(chuàng)
    發(fā)表于 09-12 06:08

    rtth studionano 如何創(chuàng)建動態(tài)線程

    有沒有大佬,可以說一下為什么靜態(tài)線程可以正常使用,動態(tài)線程怎么也使用不了。 具體需要什么配置才能使用動態(tài)線程創(chuàng)建。謝謝!
    發(fā)表于 09-11 06:01

    rtt studionano 如何創(chuàng)建動態(tài)線程?

    有沒有大佬,可以說一下為什么靜態(tài)線程可以正常使用,動態(tài)線程怎么也使用不了。 具體需要什么配置才能使用動態(tài)線程創(chuàng)建。謝謝!
    發(fā)表于 08-22 06:19

    UVC+MSC實(shí)現(xiàn)MSC線程未運(yùn)行的原因?

    我正在嘗試使用 EZUSB 運(yùn)行 UVC + MSC。我有以下內(nèi)容。但看起來只有 UVC 線程在運(yùn)行,而 MSC 沒有運(yùn)行。fw 不響應(yīng) MSC 命令。我確保 LPM 已被禁用,只是為了檢查傳感器
    發(fā)表于 07-16 07:08

    深度剖析 RT-Thread 線程調(diào)度流程

    rt_system_scheduler_start:調(diào)度系統(tǒng)第一個線程rt_hw_context_switch_to:初始化上下文切換環(huán)境,觸發(fā)PendSV異常first_thread:系統(tǒng)優(yōu)先級最高
    的頭像 發(fā)表于 06-25 18:24 ?1763次閱讀
    深度剖析 RT-Thread <b class='flag-5'>線程</b>調(diào)度流程

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

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