一、jdk的阻塞隊列:
二、Spring boot工程的有哪些阻塞隊列呢?
1、默認注入的ThreadPoolTaskExecutor
視頻解說:
線程池篇-springboot項目中的service層里簡單注入ThreadPoolTaskExecutor并且使用_嗶哩嗶哩_bilibili
程序代碼:ThreadPoolDemo/ThreadPool00 · xin麒/XinQiUtilsOrDemo - 碼云 - 開源中國 (gitee.com)
簡單在service層注入的話是這樣的:
@Autowired
ThreadPoolTaskExecutor threadPoolTaskExecutor;
同時在這里使用這個線程池:
@Override
public Object springbootThreadPool(Long count) {try {threadPoolTaskExecutor.execute(() -> {try {Thread.sleep(1000 * 1);log.debug("v me 50");} catch (InterruptedException e) {e.printStackTrace();}});} catch (Exception e) {e.printStackTrace();}return "nice";
}
以debug方式啟動項目來查看一下,發現這里默認使用的阻塞隊列是:
2、自定義ThreadPoolTaskExecutor
視頻解說:
【2】https://www.bilibili.com/video/BV1Qu4y1X7zk
【3】https://www.bilibili.com/video/BV1Cu4y1i7Ae
程序代碼:
https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/ThreadPoolDemo/ThreadPool0
驗證方式1-通過啟動springboot工程,通過debug形式查看:
@Bean("xinTaskExecutor")
public Executor xinTaskExecutor() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();//設置線程池參數信息taskExecutor.setCorePoolSize(10);taskExecutor.setMaxPoolSize(50);taskExecutor.setQueueCapacity(0);taskExecutor.setKeepAliveSeconds(60);taskExecutor.setThreadNamePrefix("xinTaskExecutor--");taskExecutor.setWaitForTasksToCompleteOnShutdown(true);taskExecutor.setAwaitTerminationSeconds(60);//修改拒絕策略為使用當前線程執行taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//初始化線程池taskExecutor.initialize();return taskExecutor;
}
驗證方式2-main方法創建并初始化:
通過debug形式查看
①查看initialize
方法就可以了
public static void main(String[] args) {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();//設置線程池參數信息taskExecutor.setCorePoolSize(10);taskExecutor.setMaxPoolSize(50);taskExecutor.setQueueCapacity(0);taskExecutor.setKeepAliveSeconds(60);taskExecutor.setThreadNamePrefix("myExecutor--");taskExecutor.setWaitForTasksToCompleteOnShutdown(true);taskExecutor.setAwaitTerminationSeconds(10);//修改拒絕策略為使用當前線程執行taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//初始化線程池taskExecutor.initialize();
}
②可以看到ExecutorConfigurationSupport
類里面有這個方法
public void initialize() {if (logger.isInfoEnabled()) {logger.info("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));}if (!this.threadNamePrefixSet && this.beanName != null) {setThreadNamePrefix(this.beanName + "-");}this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
}
直接看this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler)
③來到org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
@Override
protected ExecutorService initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);ThreadPoolExecutor executor;if (this.taskDecorator != null) {executor = new ThreadPoolExecutor(this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,queue, threadFactory, rejectedExecutionHandler) {@Overridepublic void execute(Runnable command) {Runnable decorated = taskDecorator.decorate(command);if (decorated != command) {decoratedTaskMap.put(decorated, command);}super.execute(decorated);}};}else {executor = new ThreadPoolExecutor(this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,queue, threadFactory, rejectedExecutionHandler);}if (this.allowCoreThreadTimeOut) {executor.allowCoreThreadTimeOut(true);}this.threadPoolExecutor = executor;return executor;
}
直接看createQueue(this.queueCapacity)
即可
④org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor#createQueue
可以看到要么new LinkedBlockingQueue<>(queueCapacity)
要么就new SynchronousQueue<>()
protected BlockingQueue<Runnable> createQueue(int queueCapacity) {if (queueCapacity > 0) {return new LinkedBlockingQueue<>(queueCapacity);}else {return new SynchronousQueue<>();}
}
那么有沒有其他阻塞隊列可選呢?這個我就沒詳細去看了,可以自己嘗試下找一下有沒有其他方式可以的,難道說重寫在里面的方法嗎?可行性有待驗證。如果創建一個繼承了org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
類,且重寫了createQueue
方法的話那么可以考慮下。就這樣吧。
三、和jdk的線程池的區別
1、感覺沒什么區別,因為ThreadPoolTaskExecutor
內使用的線程池本來就是成員變量中的
@Nullable
private ThreadPoolExecutor threadPoolExecutor;
2、springboot的項目里可以通過注解方式來執行方法
只不過指定使用哪個線程池來執行要異步執行方法的內容。
https://www.bilibili.com/video/BV1A14y1B78x/
如果是默認的注解來執行內容則可能有其他問題:
https://www.bilibili.com/video/BV1Gu4y1q7TY
但是可以通過注解指定使用哪個線程池:
https://www.bilibili.com/video/BV1e44y1c7uE