【线上直播】11月21日晚8点贝壳技术总监侯圣文《数据安全之数据库安全黄金法则》
看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,通过源码分析禁用的原因。
写在前面
首先感谢大家在盖楼的间隙阅读本篇文章,通过阅读本篇文章你将了解到:
- 线程池的定义
- Executors创建线程池的几种方式
- ThreadPoolExecutor对象
- 线程池执行任务逻辑和线程池参数的关系
- Executors创建返回ThreadPoolExecutor对象
- OOM异常测试
- 如何定义线程池参数
如果只想知道原因,看下面
线程池的定义
管理一组工作线程。通过线程池复用线程有以下几点优点:
减少资源创建 => 减少内存开销,创建线程占用内存
降低系统开销 => 创建线程需要时间,会延迟处理的请求
提高稳定稳定性 => 避免无限创建线程引起的OutOfMemoryError【简称OOM】
Executors创建线程池的方式
根据返回的对象类型创建线程池可以分为三类:
- 创建返回ThreadPoolExecutor对象
- 创建返回ScheduleThreadPoolExecutor对象
- 创建返回ForkJoinPool对象
本文只讨论创建返回ThreadPoolExecutor对象
ThreadPoolExecutor对象
在介绍Executors创建线程池方法前先介绍一下ThreadPoolExecutor,因为这些创建线程池的静态方法都是返回ThreadPoolExecutor对象,和我们手动创建ThreadPoolExecutor对象的区别就是我们不需要自己传构造函数的参数。
ThreadPoolExecutor的构造函数共有四个,但最终调用的都是同一个:
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable> workQueue,
- ThreadFactory threadFactory,
- RejectedExecutionHandler handler)
构造函数参数说明:
- corePoolSize => 线程池核心线程数量
- maximumPoolSize => 线程池最大数量
- keepAliveTime => 空闲线程存活时间
- unit => 时间单位
- workQueue => 线程池所使用的缓冲队列
- threadFactory => 线程池创建线程使用的工厂
- handler => 线程池对拒绝任务的处理策略
线程池执行任务逻辑和线程池参数的关系
执行逻辑说明:
- 判断核心线程数是否已满,核心线程数大小和corePoolSize参数有关,未满则创建线程执行任务
- 若核心线程池已满,判断队列是否满,队列是否满和workQueue参数有关,若未满则加入队列中
- 若队列已满,判断线程池是否已满,线程池是否已满和maximumPoolSize参数有关,若未满创建线程执行任务
- 若线程池已满,则采用拒绝策略处理无法执执行的任务,拒绝策略和handler参数有关
Executors创建返回ThreadPoolExecutor对象
Executors创建返回ThreadPoolExecutor对象的方法共有三种:
- Executors#newCachedThreadPool => 创建可缓存的线程池
- Executors#newSingleThreadExecutor => 创建单线程的线程池
- Executors#newFixedThreadPool => 创建固定长度的线程池
Executors#newCachedThreadPool方法
- public static ExecutorService newCachedThreadPool() {
- return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
- 60L, TimeUnit.SECONDS,
- new SynchronousQueue<Runnable>());
- }
(编辑:ASP站长网)
|