場景:
某個定時任務需要多線程執行,執行時間較久且每天只跑一次,想單獨拉出一個線程池和其他業務隔離開,交給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,並且不是定時任務的話 這樣操作是一個極度極度危險的操作,很快會把線程資源耗盡
