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

Spring Boot配置線程池拒絕策略的場景分析(妥善處理好溢出的任務(wù))

 更新時間:2021年09月24日 09:28:23   作者:程序猿DD  
本文通過實例代碼給大家介紹下如何為線程池配置拒絕策略、如何自定義拒絕策略。對Spring Boot配置線程池拒絕策略的相關(guān)知識感興趣的朋友一起看看吧

通過之前三篇關(guān)于Spring Boot異步任務(wù)實現(xiàn)的博文,我們分別學(xué)會了用@Async創(chuàng)建異步任務(wù)、為異步任務(wù)配置線程池、使用多個線程池隔離不同的異步任務(wù)。今天這篇,我們繼續(xù)對上面的知識進行完善和優(yōu)化!

如果你已經(jīng)看過上面幾篇內(nèi)容并已經(jīng)掌握之后,一起來思考下面這個問題:

假設(shè),線程池配置為核心線程數(shù)2、最大線程數(shù)2、緩沖隊列長度2。此時,有5個異步任務(wù)同時開始,會發(fā)生什么?

場景重現(xiàn)

我們先來把上面的假設(shè)用代碼實現(xiàn)一下:

第一步:創(chuàng)建Spring Boot應(yīng)用,根據(jù)上面的假設(shè)寫好線程池配置。

@EnableAsync
@SpringBootApplication
public class Chapter78Application {

    public static void main(String[] args) {
        SpringApplication.run(Chapter78Application.class, args);
    }

    @EnableAsync
    @Configuration
    class TaskPoolConfig {

        @Bean
        public Executor taskExecutor1() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(2);
            executor.setMaxPoolSize(2);
            executor.setQueueCapacity(2);
            executor.setKeepAliveSeconds(60);
            executor.setThreadNamePrefix("executor-1-");
            return executor;
        }

    }

}

第二步:用@Async注解實現(xiàn)一個部分任務(wù)

@Slf4j
@Component
public class AsyncTasks {

    public static Random random = new Random();

    @Async("taskExecutor1")
    public CompletableFuture<String> doTaskOne(String taskNo) throws Exception {
        log.info("開始任務(wù):{}", taskNo);
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("完成任務(wù):{},耗時:{} 毫秒", taskNo, end - start);
        return CompletableFuture.completedFuture("任務(wù)完成");
    }

}

第三步:編寫測試用例

@Slf4j
@SpringBootTest
public class Chapter78ApplicationTests {

    @Autowired
    private AsyncTasks asyncTasks;

    @Test
    public void test2() throws Exception {
        // 線程池配置:core-2,max-2,queue=2,同時有5個任務(wù),出現(xiàn)下面異常:
        // org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@59901c4d[Running, pool size = 2,
        // active threads = 0, queued tasks = 2, completed tasks = 4]] did not accept task: java.util.concurrent.CompletableFuture$AsyncSupply@408e96d9

        long start = System.currentTimeMillis();

        // 線程池1
        CompletableFuture<String> task1 = asyncTasks.doTaskOne("1");
        CompletableFuture<String> task2 = asyncTasks.doTaskOne("2");
        CompletableFuture<String> task3 = asyncTasks.doTaskOne("3");
        CompletableFuture<String> task4 = asyncTasks.doTaskOne("4");
        CompletableFuture<String> task5 = asyncTasks.doTaskOne("5");

        // 一起執(zhí)行
        CompletableFuture.allOf(task1, task2, task3, task4, task5).join();

        long end = System.currentTimeMillis();

        log.info("任務(wù)全部完成,總耗時:" + (end - start) + "毫秒");
    }

}

執(zhí)行一下,可以類似下面這樣的日志信息:

2021-09-22 17:33:08.159  INFO 21119 --- [   executor-1-2] com.didispace.chapter78.AsyncTasks       : 開始任務(wù):2
2021-09-22 17:33:08.159  INFO 21119 --- [   executor-1-1] com.didispace.chapter78.AsyncTasks       : 開始任務(wù):1

org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@3e1a3801[Running, pool size = 2, active threads = 2, queued tasks = 2, completed tasks = 0]] did not accept task: java.util.concurrent.CompletableFuture$AsyncSupply@64968732

 at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:324)
 at java.util.concurrent.CompletableFuture.asyncSupplyStage(CompletableFuture.java:1604)
 at java.util.concurrent.CompletableFuture.supplyAsync(CompletableFuture.java:1830)
 at org.springframework.aop.interceptor.AsyncExecutionAspectSupport.doSubmit(AsyncExecutionAspectSupport.java:274)
 at org.springframework.aop.interceptor.AsyncExecutionInterceptor.invoke(AsyncExecutionInterceptor.java:129)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
 at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
 at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
 at com.didispace.chapter78.AsyncTasks$$EnhancerBySpringCGLIB$$c7e8d57b.doTaskOne(<generated>)
 at com.didispace.chapter78.Chapter78ApplicationTests.test2(Chapter78ApplicationTests.java:51)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
 at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
 at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
 at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
 at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
 at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
 at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
 at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
 at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
 at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
 at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
 at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
 at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
 at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
 at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
 at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
 at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
 at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
 at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
 at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
 at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
 at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
 at java.util.ArrayList.forEach(ArrayList.java:1255)
 at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
 at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
 at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
 at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
 at java.util.ArrayList.forEach(ArrayList.java:1255)
 at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
 at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
 at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
 at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
 at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
 at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
 at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
 at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
 at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
 at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
 at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
 at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
 at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
 at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
 at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
 at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
 at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
 at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.CompletableFuture$AsyncSupply@64968732 rejected from java.util.concurrent.ThreadPoolExecutor@3e1a3801[Running, pool size = 2, active threads = 2, queued tasks = 2, completed tasks = 0]
 at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
 at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
 at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
 at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:321)
 ... 74 more

從異常信息org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@3e1a3801[Running, pool size = 2, active threads = 2, queued tasks = 2, completed tasks = 0]] did not accept task: 中,可以很明確的知道,第5個任務(wù)因為超過了執(zhí)行線程+緩沖隊列長度,而被拒絕了。

所有,默認情況下,線程池的拒絕策略是:當(dāng)線程池隊列滿了,會丟棄這個任務(wù),并拋出異常。

配置拒絕策略

雖然線程池有默認的拒絕策略,但實際開發(fā)過程中,有些業(yè)務(wù)場景,直接拒絕的策略往往并不適用,有時候我們可能會選擇舍棄最早開始執(zhí)行而未完成的任務(wù)、也可能會選擇舍棄剛開始執(zhí)行而未完成的任務(wù)等更貼近業(yè)務(wù)需要的策略。所以,為線程池配置其他拒絕策略或自定義拒絕策略是很常見的需求,那么這個要怎么實現(xiàn)呢?

下面就來具體說說今天的正題,如何為線程池配置拒絕策略、如何自定義拒絕策略。

看下面這段代碼的最后一行,setRejectedExecutionHandler方法就是為線程池設(shè)置拒絕策略的方法:

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

//...其他線程池配置

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

ThreadPoolExecutor中提供了4種線程的策略可以供開發(fā)者直接使用,你只需要像下面這樣設(shè)置即可:

// AbortPolicy策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());

// DiscardPolicy策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());

// DiscardOldestPolicy策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());

// CallerRunsPolicy策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

這四個策略對應(yīng)的含義分別是:

  • AbortPolicy策略:默認策略,如果線程池隊列滿了丟掉這個任務(wù)并且拋出RejectedExecutionException異常。
  • DiscardPolicy策略:如果線程池隊列滿了,會直接丟掉這個任務(wù)并且不會有任何異常。
  • DiscardOldestPolicy策略:如果隊列滿了,會將最早進入隊列的任務(wù)刪掉騰出空間,再嘗試加入隊列。
  • CallerRunsPolicy策略:如果添加到線程池失敗,那么主線程會自己去執(zhí)行該任務(wù),不會等待線程池中的線程去執(zhí)行。

而如果你要自定義一個拒絕策略,那么可以這樣寫:

executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 拒絕策略的邏輯
    }
});

當(dāng)然如果你喜歡用Lamba表達式,也可以這樣寫:

executor.setRejectedExecutionHandler((r, executor1) -> {
    // 拒絕策略的邏輯
});

好了,今天的學(xué)習(xí)就到這里!

代碼示例

本文的完整工程可以查看下面?zhèn)}庫中2.x目錄下的chapter7-8工程:

到此這篇關(guān)于Spring Boot配置線程池拒絕策略,妥善處理好溢出的任務(wù)的文章就介紹到這了,更多相關(guān)Spring Boot配置線程池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java使用freemarker模板生成html再轉(zhuǎn)為pdf

    java使用freemarker模板生成html再轉(zhuǎn)為pdf

    這篇文章主要為大家詳細介紹了java如何使用freemarker模板生成html,再利用iText將生成的HTML轉(zhuǎn)換為PDF文件,感興趣的小伙伴可以參考下
    2025-04-04
  • java操作xml的方法匯總及解析

    java操作xml的方法匯總及解析

    這篇文章主要介紹了java操作xml的方法匯總及解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Java調(diào)用Pytorch模型實現(xiàn)圖像識別

    Java調(diào)用Pytorch模型實現(xiàn)圖像識別

    這篇文章主要為大家詳細介紹了Java如何調(diào)用Pytorch實現(xiàn)圖像識別功能,文中的示例代碼講解詳細,具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解一下
    2023-06-06
  • SpringMVC異步處理操作(Callable和DeferredResult)

    SpringMVC異步處理操作(Callable和DeferredResult)

    這篇文章主要介紹了SpringMVC異步處理操作(Callable和DeferredResult),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Java中的WeakHashMap源碼分析

    Java中的WeakHashMap源碼分析

    這篇文章主要介紹了Java中的WeakHashMap源碼分析,WeakHashMap可能平時使用的頻率并不高,但是你可能聽過WeakHashMap會進行自動回收吧,下面就對其原理進行分析,需要的朋友可以參考下
    2023-09-09
  • 手動編譯并運行Java項目實現(xiàn)過程解析

    手動編譯并運行Java項目實現(xiàn)過程解析

    這篇文章主要介紹了手動編譯并運行Java項目實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-10-10
  • springboot自動配置原理以及spring.factories文件的作用詳解

    springboot自動配置原理以及spring.factories文件的作用詳解

    這篇文章主要介紹了springboot自動配置原理以及spring.factories文件的作用詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java synchronized實現(xiàn)可見性過程解析

    java synchronized實現(xiàn)可見性過程解析

    這篇文章主要介紹了java synchronized實現(xiàn)可見性過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • 解決SpringBoot掃描不到公共類的實體問題

    解決SpringBoot掃描不到公共類的實體問題

    這篇文章主要介紹了解決SpringBoot掃描不到公共類的實體問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Map集合之HashMap的使用及說明

    Map集合之HashMap的使用及說明

    這篇文章主要介紹了Map集合之HashMap的使用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10

最新評論

绍兴市| 大名县| 高雄市| 明水县| 岑巩县| 霍邱县| 孟州市| 泽州县| 雅江县| 天镇县| 明水县| 那坡县| 乐至县| 互助| 江陵县| 丁青县| 鄂托克旗| 连南| 定日县| 抚顺市| 哈巴河县| 新晃| 邛崃市| 理塘县| 桂东县| 嵊泗县| 同江市| 西吉县| 清丰县| 宜阳县| 景宁| 永寿县| 陇西县| 合山市| 盘锦市| 康定县| 平陆县| 灌云县| 阿坝县| 阿合奇县| 阜新|