1. 程式人生 > >SpringBoot使用非同步執行緒池使程式無法關閉

SpringBoot使用非同步執行緒池使程式無法關閉

又是一個困擾我在整整一天的難題,到了快23點,終於結束了,雖然很想睡覺,但還是得把它記錄下來.                                               

今天在一個springBoot程式中想使用多執行緒(我的程式不是web),網上的教程有很多,大多都是使用

ThreadPoolTaskExecutor配合spring的非同步註釋@EnableAsync和@Async,具體的實現很簡單,

網上的教程大抵上都差不多,如果想要了解,可以看這個SpringBoot對多執行緒的支援詳解.這個例子很簡單,

當我使用其中的多執行緒的配置完成後,關於執行緒池的執行任務方面完全沒有問題,但是這個時候出現一個問題,

你也可以自己執行上面的教程中的例子,你會發現當執行緒池執行完任務後,整個SpringBoot被阻塞了,

沒有關閉,就卡線上程池的任務執行完那裡,就我後面解決後的理解來看,是執行緒池沒有關閉,具體的原因我並不知道,

但是我猜測是因為SpringBoot對這個執行緒池的支援是非同步的,一般非同步執行緒是需要Future配合通知關閉的,

然後我就開始搜尋答案,百度顯然不管用,國內的帖子的解決辦法只有一個,就是線上程池的建立的地方加上

setWaitForTasksToCompleteOnShutdown(true),
setAwaitTerminationSeconds(60);

大致的意思看名字就可以以看的出來,就是等60秒後關閉,但是這個並沒有什麼亂用,然後我就遁入stackoverflow,

這裡的解決方案就很多了,我試了幾種,再結合自己的理解,找到了一種方法,就是在最後執行的主類中

加入一個之前配置的ThreadPoolTaskExecutor的Bean,顯性的執行完執行緒後執行shutdown(),

有一點需要注意的是,上面的例子中的執行內容很簡單,可能主執行緒在其他任務沒有執行完成前就獲得了執行的許可權,

導致任務沒有執行完,就關閉了執行緒池,這裡就需要一個Java併發工具CountDownLatch,

大家可以自行了解使用,我覺得和join沒什麼區別,但是需要線上程池中使用,好了問題就這樣了