原文:https://www.jianshu.com/p/832f2b162450css
咱們都知道spring只是爲咱們簡單的處理線程池,每次用到線程總會new 一個新的線程,效率不高,因此咱們須要自定義一個線程池。java
本教程目錄:spring
task.pool.corePoolSize=20 task.pool.maxPoolSize=40 task.pool.keepAliveSeconds=300 task.pool.queueCapacity=50
import org.springframework.boot.context.properties.ConfigurationProperties; /** * 線程池配置屬性類 * Created by Fant.J. */ @ConfigurationProperties(prefix = "task.pool") public class TaskThreadPoolConfig { private int corePoolSize; private int maxPoolSize; private int keepAliveSeconds; private int queueCapacity; ...getter and setter methods... }
/** * 建立線程池 * Created by Fant.J. */ @Configuration @EnableAsync public class TaskExecutePool { @Autowired private TaskThreadPoolConfig config; @Bean public Executor myTaskAsyncPool() { 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; } }
/** * Created by Fant.J. */ @Component public class AsyncTask { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @Async("myTaskAsyncPool") //myTaskAsynPool即配置線程池的方法名,此處若是不寫自定義線程池的方法名,會使用默認的線程池 public void doTask1(int i) throws InterruptedException{ logger.info("Task"+i+" started."); } }
給啓動類添加註解app
@EnableAsync @EnableConfigurationProperties({TaskThreadPoolConfig.class} ) // 開啓配置屬性支持
protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private AsyncTask asyncTask; @Test public void AsyncTaskTest() throws InterruptedException, ExecutionException { for (int i = 0; i < 100; i++) { asyncTask.doTask1(i); } logger.info("All tasks finished."); }
我本人喜歡用這種方式的線程池,由於上面的那個線程池使用時候總要加註解@Async("myTaskAsyncPool")
,而這種重寫spring默認線程池的方式使用的時候,只須要加@Async
註解就能夠,不用去聲明線程池類。異步
這個和上面的TaskThreadPoolConfig類相同,這裏不重複async
/** * 原生(Spring)異步任務線程池裝配類 * Created by Fant.J. */ @Slf4j @Configuration public class NativeAsyncTaskExecutePool implements AsyncConfigurer{ //注入配置類 @Autowired TaskThreadPoolConfig 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; } /** * 異步任務中異常處理 * @return */ @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new AsyncUncaughtExceptionHandler() { @Override public void handleUncaughtException(Throwable arg0, Method arg1, Object... arg2) { log.error("=========================="+arg0.getMessage()+"=======================", arg0); log.error("exception method:"+arg1.getName()); } }; } }
@Component public class AsyncTask { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @Async public void doTask2(int i) throws InterruptedException{ logger.info("Task2-Native"+i+" started."); } }
@Test public void AsyncTaskNativeTest() throws InterruptedException, ExecutionException { for (int i = 0; i < 100; i++) { asyncTask.doTask2(i); } logger.info("All tasks finished."); }
2018-03-25 21:23:07.655 INFO 4668 --- [ MyExecutor-8] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native6 started. 2018-03-25 21:23:07.655 INFO 4668 --- [ MyExecutor-3] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native1 started. 2018-03-25 21:23:07.655 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native7 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native21 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native22 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native23 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native24 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native25 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native26 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native27 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native28 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native29 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native30 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native31 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native32 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native33 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native34 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native35 started. 2018-03-25 21:23:07.656 INFO 4668 --- [ MyExecutor-9] c.l.securitydemo.mythreadpool.AsyncTask : Task2-Native36 started. 2018-03-25 21