线程池的主要处理流程及常用方法
更多优秀文章,请扫码关注个人微信公众号或搜索“程序猿小杨”添加。
一、主要处理流程:
当调用线程池execute() 方法添加一个任务时,
threadPoolExecutor.execute,具体代码如下:
private void batchOpSpilit(List<Student> list, int batch100) {
log.info("开始切割………………");
List<List<Student>> list1 = SplitListUtils.pagingList(list, batch100);
try {
for (List<Student> list2 : list1) {
// threadPoolExecutor.allowCoreThreadTimeOut(true);
//再调batchOp方法,这里的多线程是多个小集合往数据库插入
threadPoolExecutor.execute(() -> {
log.info("我是线程开始保存数据...:" + Thread.currentThread().getName());
batchOp(list2);
});
}
log.info("当前线程池剩余的数量222222:"+threadPoolExecutor.getPoolSize());
} catch (Exception e) {
log.info("出现异常:"+e);
} finally {
//最后关闭线程 不允许提交新的任务,但是会处理完已提交的任务
threadPoolExecutor.shutdown();
}
}
线程池会做如下判断:
1、若核心线程池(corePoolSize)未满,创建核心线程执行任务;
2、若核心线程池(corePoolSize)已经满,且队列(workQueue)未满,则任务添加到队列中等待执行,而不添加新的线程。
3、若队列(workQueue)已经满,同时池中的线程数小于maximumPoolSize ,则创建新的线程执行任务;
4、若核心线程池(corePoolSize)已经满,且阻塞队列(workQueue)已满,同时池中的线程数等于maximumPoolSize ,则根据构造函数中的 handler 指定的策略来拒绝新的任务。
二、案例说明:
如果有一个corePoolSize为5,maximumPoolSize为10的线程池,可用下图形象展示:
/**线程池*/
private ThreadPoolExecutor threadPoolExecutor =
new ThreadPoolExecutor(
5, //corePoolSize:线程池中核心线程数
10, //线程池中能拥有最多线程数
5L, //keepAliveTime:表示空闲线程的存活时间 2秒
TimeUnit.SECONDS, //表示keepAliveTime的单位:秒
new LinkedBlockingQueue<>(100), //用于缓存任务的阻塞队列
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
备注:所谓核心线程,非核心线程只是一个数量的说明,并不是说两者有本质上的不同,都是普通的线程而已,且线程特性都一样,并不是说核心线程有特殊标记,线程池能“认”出来这是核心线程,对其有特殊操作。
三、线程池的状态:
四、常用方法:
更多优秀文章,请扫码关注个人微信公众号或搜索“程序猿小杨”添加。
1、SpringBoot使用@Async实现多线程异步;
2、线程池的主要处理流程及常用方法
3、为什么推荐使用线程池?