Java ——线程池
线程池的自我介绍
如果不使用线程池,新建线程则属于每个任务新建一个线程,当线程数据过大时,则会导致OOM
线程池的好处在于:
① 加快响应速度
②合理利用CPU及内存
③ 统一管理
适用场景:
- 批量计算任务,服务器处理请求,excel解析等
- 开发中,超过,超过5个以上的线程使用,则可以使用线程池
创建、停止线程池
线程池构建有几个重要的参数:分别是 核心线程数 最大线程数 保持存活时间 任务存储队列,新线程生成器,拒绝策略
其中更值得重点关注的是 核心线程数,最大线程数,存储队列以及拒绝策略
当 最大线程 =核心线程时,说明线程池为固定大小
当最大线程池超级大时,说明允许任意数量并发任务
当使用无界队列时,线程数不会大于核心线程数
KeepAliveTime 参数是指 如果当前线程数大于核心线程数时,且多余线程空闲时间大于KeepAliveTime会终止。
ThreadFactory:默认使用Executors.defaultThreadFactory() 创建出来的线程都在一个线程组中。
如果自己指定线程工厂,则可以修改线程名,线程组优先级,是否是守护线程等等。
工作队列:
①直接交换队列 SynchronousQueue :需要大max
②无界队列 LinkedBlockingQueue :max属性无用
③有界队列 ArrayBlockingQueue
所以我们还是手动创建线程池比较好,因为可以熟悉掌握上述几个重要属性
线程池大小也有计算方法:(CPU核*(1+平等/平工作))
停止线程池也有方法:
1.shutDown 初始化关闭线程过程,表明不再接受新任务,但是已有任务会继续执行完
查看停止没 isShutDown() 查看真终止 isTermination()
2.等待一段时间后,判断线程池是否关闭 awaitTermination() 等待一段时间是否执行完成,此段过程任务阻塞
3.shutDownNow 立即关闭线程池,执行中立即断开,队列中直接返回
常见线程池特点及用法
FixedThreadPool 核心等于最大 ,队列满时无法增加线程,直接拒绝 采用LinkedBlockingQueue 无界存储
CachedThreadPool 可缓存线程池,自动回收多余线程,队列无容器 SynchronousQueue
ScheduleThreadPool 支持周期性任务的线程池DelayedWorkQueue 存储
SingleThreadExecutor 单线程线程池 采用LinkedBlockingQueue 存储
任务太多如何拒绝
拒绝时机:
Executor关闭后,新任务立即拒绝
最大线程和队列均满时拒绝
有四种拒绝策略:
- AbortPolicy :直接抛出异常
- DiscardPolicy 默默丢弃
- DiscardOldestPolicy 丢弃最老的
- CallerRunsPolicy 谁提交谁执行 -避免丢弃,降低提交速度
线程池实现服用的原理其实是相同线程执行不同任务
同时引入可重入锁概念。
线程池注意点
手动创建
线程数需合理
考虑多线程池影响