場景:
某個定時任務需要多線程執行,執行時間較久且每天只跑一次,想單獨拉出一個線程池和其他業務隔離開,交給spring會導致核心線程一直存在 浪費線程資源,因此想單獨拉一個池子用完就丟,原本想的是,在execute之后,核心線程會隨着線程池對象的回收而回收,后來轉念一想,核心線程池怎么回收?寫了個main方法試驗了一下
public class Test { public static void main(String[] args) { List<Long> memberIds=new ArrayList<>(); for (long i=0;i<3600;i++){ memberIds.add(i); } boolean hasleft=true; int index=0; int pageSize=450; while(hasleft){ int endIndex=Math.min((index+1)*pageSize,memberIds.size()); if (endIndex>=memberIds.size()){ hasleft=false; } List<Long> executeMemberIds=memberIds.subList(index++*pageSize,endIndex); ExecutorService executorService= Executors.newCachedThreadPool(); if (CollectionUtils.isNotEmpty(executeMemberIds)){ executorService.execute(new Runnable() { @Override public void run() { System.out.println(executeMemberIds); } }); } //TODO 很關鍵 一定要shutdown!否則,不僅核心線程不會回收,業務線程也不會結束,很危險 // executorService.shutdown(); } } }
在沒有shutdonwn的時候main方法執行完成后並不會結束線程,自然核心線程也不會被回收,后續了解到核心線程也是可以配置超時時間被回收的,但是一般默認是false,比較好的做法是在把任務交給線程池之后,shutdown()通知線程池,在消費完所有的任務之后回收資源。而shutdownNow()則會終止正在進行的任務進行回收。所以如果沒有shutdown,並且不是定時任務的話 這樣操作是一個極度極度危險的操作,很快會把線程資源耗盡