spring boot使用自定义的线程池执行Async任务
在前面的博客中,https://www.nhooo.com/article/134866.htm我们使用了springboot的异步操作,当时,我们使用的是默认的线程池,但是,如果我们想根据项目来定制自己的线程池了,下面就来说说,如何定制线程池!
一、增加配置属性类
packagecom.chhliu.springboot.async.configuration; importorg.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix="spring.task.pool")//该注解的locations已经被启用,现在只要是在环境中,都会优先加载 publicclassTaskThreadPoolConfig{ privateintcorePoolSize; privateintmaxPoolSize; privateintkeepAliveSeconds; privateintqueueCapacity; …………省略getter,setter方法………… }
二、创建线程池
packagecom.chhliu.springboot.async.pool; importjava.util.concurrent.Executor; importjava.util.concurrent.ThreadPoolExecutor; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.scheduling.annotation.EnableAsync; importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; importcom.chhliu.springboot.async.configuration.TaskThreadPoolConfig; @Configuration @EnableAsync publicclassTaskExecutePool{ @Autowired privateTaskThreadPoolConfigconfig; @Bean publicExecutormyTaskAsyncPool(){ ThreadPoolTaskExecutorexecutor=newThreadPoolTaskExecutor(); executor.setCorePoolSize(config.getCorePoolSize()); executor.setMaxPoolSize(config.getMaxPoolSize()); executor.setQueueCapacity(config.getQueueCapacity()); executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); executor.setThreadNamePrefix("MyExecutor-"); //rejection-policy:当pool已经达到maxsize的时候,如何处理新任务 //CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); returnexecutor; } }
三、在主类中开启配置支持
packagecom.chhliu.springboot.async; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; importorg.springframework.boot.context.properties.EnableConfigurationProperties; importorg.springframework.scheduling.annotation.EnableAsync; importcom.chhliu.springboot.async.configuration.TaskThreadPoolConfig; @SpringBootApplication @EnableAsync @EnableConfigurationProperties({TaskThreadPoolConfig.class})//开启配置属性支持 publicclassSpringbootAsyncApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(SpringbootAsyncApplication.class,args); } }
四、测试类
packagecom.chhliu.springboot.async.pool; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.scheduling.annotation.Async; importorg.springframework.stereotype.Component; @Component publicclassAsyncTask{ protectedfinalLoggerlogger=LoggerFactory.getLogger(this.getClass()); @Async("myTaskAsyncPool")//myTaskAsynPool即配置线程池的方法名,此处如果不写自定义线程池的方法名,会使用默认的线程池 publicvoiddoTask1(inti)throwsInterruptedException{ logger.info("Task"+i+"started."); } }
五、测试
packagecom.chhliu.springboot.async; importjava.util.concurrent.ExecutionException; importorg.junit.Test; importorg.junit.runner.RunWith; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.boot.test.context.SpringBootTest; importorg.springframework.test.context.junit4.SpringRunner; importcom.chhliu.springboot.async.pool.AsyncTask; @RunWith(SpringRunner.class) @SpringBootTest publicclassSpringbootAsyncApplicationTests{ protectedfinalLoggerlogger=LoggerFactory.getLogger(this.getClass()); @Autowired privateAsyncTaskasyncTask; @Test publicvoidAsyncTaskTest()throwsInterruptedException,ExecutionException{ for(inti=0;i<100;i++){ asyncTask.doTask1(i); } logger.info("Alltasksfinished."); } }
测试结果如下:
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-10]c.c.springboot.async.pool.AsyncTask :Task60started.
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-25]c.c.springboot.async.pool.AsyncTask :Task61started.
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-6]c.c.springboot.async.pool.AsyncTask :Task62started.
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-23]c.c.springboot.async.pool.AsyncTask :Task63started.
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-20]c.c.springboot.async.pool.AsyncTask :Task64started.
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-19]c.c.springboot.async.pool.AsyncTask :Task65started.
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-16]c.c.springboot.async.pool.AsyncTask :Task66started.
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-15]c.c.springboot.async.pool.AsyncTask :Task67started.
2017-03-2020:15:15.208 INFO4068---[ MyExecutor-12]c.c.springboot.async.pool.AsyncTask :Task68started.
2017-03-2020:15:15.209 INFO4068---[ MyExecutor-1]c.c.springboot.async.pool.AsyncTask :Task69started.
2017-03-2020:15:15.209 INFO4068---[ MyExecutor-11]c.c.springboot.async.pool.AsyncTask :Task81started.
2017-03-2020:15:15.209 INFO4068---[ MyExecutor-8]c.c.springboot.async.pool.AsyncTask :Task82started.
2017-03-2020:15:15.209 INFO4068---[ MyExecutor-7]c.c.springboot.async.pool.AsyncTask :Task83started.
2017-03-2020:15:15.209 INFO4068---[ MyExecutor-4]c.c.springboot.async.pool.AsyncTask :Task84started.
2017-03-2020:15:15.209 INFO4068---[ MyExecutor-29]c.c.springboot.async.pool.AsyncTask :Task85started.
2017-03-2020:15:15.209 INFO4068---[ MyExecutor-21]c.c.springboot.async.pool.AsyncTask :Task86started.
2017-03-2020:15:15.209 INFO4068---[ MyExecutor-17]c.c.springboot.async.pool.AsyncTask :Task88started.
测试结果ok!
六、配置默认的线程池
如果我们想使用默认的线程池,但是只是想修改默认线程池的配置,那怎么做了,此时我们需要实现AsyncConfigurer类,示例代码如下:
importjava.lang.reflect.Method; importjava.util.concurrent.Executor; importjava.util.concurrent.ThreadPoolExecutor; importorg.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.context.annotation.Configuration; importorg.springframework.scheduling.annotation.AsyncConfigurer; importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; importcom.chhliu.cq.emailservice.threadconfiguration.TaskThreadPoolConfig; importlombok.extern.slf4j.Slf4j; /** *注意:该线程池被所有的异步任务共享,而不属于某一个异步任务 *描述:配置异步任务的线程池 *@authorchhliu *创建时间:2017年5月22日上午10:20:56 *@version1.2.0 */ @Slf4j @Configuration publicclassAsyncTaskExecutePoolimplementsAsyncConfigurer{ @Autowired privateTaskThreadPoolConfigconfig;//配置属性类,见上面的代码 @Override publicExecutorgetAsyncExecutor(){ ThreadPoolTaskExecutorexecutor=newThreadPoolTaskExecutor(); executor.setCorePoolSize(config.getCorePoolSize()); executor.setMaxPoolSize(config.getMaxPoolSize()); executor.setQueueCapacity(config.getQueueCapacity()); executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); executor.setThreadNamePrefix("taskExecutor-"); //rejection-policy:当pool已经达到maxsize的时候,如何处理新任务 //CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); returnexecutor; } @Override publicAsyncUncaughtExceptionHandlergetAsyncUncaughtExceptionHandler(){//异步任务中异常处理 returnnewAsyncUncaughtExceptionHandler(){ @Override publicvoidhandleUncaughtException(Throwablearg0,Methodarg1,Object...arg2){ log.error("=========================="+arg0.getMessage()+"=======================",arg0); log.error("exceptionmethod:"+arg1.getName()); } }; } }
使用的时候,只需在方法上加上@Async即可。
总结
以上所述是小编给大家介绍的springboot使用自定义的线程池执行Async任务,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!