SpringBoot自定義線程池


使用SpringBoot構建應用時,如何使用線程處理異步任務?其實springBoot已經提供了默認的實現,通過在啟動類上加上注解@EnableAsync, 然后在需要異步處理的方法上增加注解@Async即可啟動一個線程進行異步處理。其實質類似於:new Thread(()-{System.out.print("處理異步任務")}).start()。但需要注意的是@Async默認使用的是SimpleAsyncTaskExecutor,每次提交任務都創建線程,要小心在使用大任務的場景下創建大量線程導致OOM異常。所以,還是自定義線程池好。自定義線程池有2種實現方式。

1. 自定義線程池,然后使用自己定義的線程池

  1.1 修改application.yml文件,增加線程池的配置參數,如下

   

 

 

 1.2 線程池配置屬性類MyThreadPoolConfig .java

/**
* 線程池配置屬性類
*/

@ConfigurationProperties(prefix = "mytask.pool")

public class MyThreadPoolConfig {
private int corePoolSize;

private int maxPoolSize;

private int keepAliveSeconds;

private int queueCapacity;

}

 

1.3  啟動類上一定要開啟線程異步支持:@EnableAsync

@EnableAsync
@EnableConfigurationProperties({MyThreadPoolConfig.class})
@SpringCloudApplication

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

 

1.4 創建自己的線程池

      

/**
 * 創建線程池
 */
@Configuration
public class MyTaskExecutePool {
 
    @Autowired
    private MyThreadPoolConfig config;
 
    @Bean("myTaskPool")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心線程池大小
        executor.setCorePoolSize(config.getCorePoolSize());
        //最大線程數
        executor.setMaxPoolSize(config.getMaxPoolSize());
        //隊列容量
        executor.setQueueCapacity(config.getQueueCapacity());
        //活躍時間
        executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
        //線程名字前綴
        executor.setThreadNamePrefix("TaskExecutePool-");
 
        // setRejectedExecutionHandler:當pool已經達到maxSize的時候,如何處理新進任務
        // CallerRunsPolicy:不在新線程中執行任務,而是由調用者所在的線程來執行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
         // 等待所有任務結束后再關閉線程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
}

 

  需要注意的是這樣定義的線程池在使用的時候要在@Async主鍵里指定名稱,如:@Async("mytaskExecutor"), 否則會使用spingtBoot提供的默認線程池。

2. 重新spring默認的線程池

  第一種方式創建的線程池在使用的時候必須要指明異步任務要使用的線程池名稱,而重新srping默認的線程池,則不需要指定名稱,直接寫@Asyncj即可。

  配置方式和方式一類似,唯一的區別在於配置類要實現AsyncConfigurer

  

/**
* 重新SpringBoot默認的線程池
*/
@Configuration
public class OverrideAsyncTaskExecutePool implements AsyncConfigurer{


//注入配置類
@Autowired
MyThreadPoolConfig config;

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心線程池大小
executor.setCorePoolSize(config.getCorePoolSize());
//最大線程數
executor.setMaxPoolSize(config.getMaxPoolSize());
//隊列容量
executor.setQueueCapacity(config.getQueueCapacity());
//活躍時間
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
//線程名字前綴
executor.setThreadNamePrefix("MyExecutor-");

// setRejectedExecutionHandler:當pool已經達到max size的時候,如何處理新任務
// CallerRunsPolicy:不在新線程中執行任務,而是由調用者所在的線程來執行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM