SpringBoot使用非同步執行緒池使程式無法關閉
又是一個困擾我在整整一天的難題,到了快23點,終於結束了,雖然很想睡覺,但還是得把它記錄下來.
今天在一個springBoot程式中想使用多執行緒(我的程式不是web),網上的教程有很多,大多都是使用
ThreadPoolTaskExecutor配合spring的非同步註釋@EnableAsync和@Async,具體的實現很簡單,
網上的教程大抵上都差不多,如果想要了解,可以看這個SpringBoot對多執行緒的支援詳解.這個例子很簡單,
當我使用其中的多執行緒的配置完成後,關於執行緒池的執行任務方面完全沒有問題,但是這個時候出現一個問題,
你也可以自己執行上面的教程中的例子,你會發現當執行緒池執行完任務後,整個SpringBoot被阻塞了,
沒有關閉,就卡線上程池的任務執行完那裡,就我後面解決後的理解來看,是執行緒池沒有關閉,具體的原因我並不知道,
但是我猜測是因為SpringBoot對這個執行緒池的支援是非同步的,一般非同步執行緒是需要Future配合通知關閉的,
然後我就開始搜尋答案,百度顯然不管用,國內的帖子的解決辦法只有一個,就是線上程池的建立的地方加上
setWaitForTasksToCompleteOnShutdown(true),
setAwaitTerminationSeconds(60);
大致的意思看名字就可以以看的出來,就是等60秒後關閉,但是這個並沒有什麼亂用,然後我就遁入stackoverflow,
這裡的解決方案就很多了,我試了幾種,再結合自己的理解,找到了一種方法,就是在最後執行的主類中
加入一個之前配置的ThreadPoolTaskExecutor的Bean,顯性的執行完執行緒後執行shutdown(),
有一點需要注意的是,上面的例子中的執行內容很簡單,可能主執行緒在其他任務沒有執行完成前就獲得了執行的許可權,
導致任務沒有執行完,就關閉了執行緒池,這裡就需要一個Java併發工具CountDownLatch,
大家可以自行了解使用,我覺得和join沒什麼區別,但是需要線上程池中使用,好了問題就這樣了