目录
1. 作用
线程的创建和销毁,都是比较消耗资源,代价比较大的.然而池,可以实现,不用反复创建对象,可以复用.
2. 创建线程池时对于其中参数的理解
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize: 核心线程数
maximumPoolSize: 最大线程数
keepAliveTime: 空闲时间数量
unit: 空闲时间单位
workQueue: 阻塞/任务/工作队列
threadFactory: 线程创建的工厂
handler: 拒绝策略
3. 线程池执行流程
根据上图场景,我们可以将自己想象成快递站的老板,试想一下,假如此时一有人过来寄东西了,那我就雇佣一个临时工,等处理完了,立马就将他解雇,可以是可以,但是好像不太划算,毕竟频繁的雇佣解雇临时工开销开始比较大的.
灵机一动,我决定按照自己店里的实际需要,聘请 3 位正式员工,要是他们仨都忙着,那我就将要寄出的包裹先放在我的小店里,等他们三个将手里的包裹处理完了之后,就继续处理小店里堆积的包裹,开销也不是很大,日子过的云淡风轻~
但是没想到,618活动来的让我措手不及,很快我的小店就堆满了,三个正式员工也处理不过来,那这个时候还有人来寄包裹可怎么办,不能伤了寄件人的心呀~为了展示我们的实力,小店虽小,还是能多站下几个人的,不要慌,我再雇佣临时工不就好了嘛,场地限制,我的店里最多只能站6个人,也就是我最多同时只能雇3个临时工,这下舒坦了.
但是好日子没几天,还是我太稚嫩,低估了消费者的实力,很快,包裹堆满了小店,看着他们六个人忙的不可开交,我也是心疼,此时,还有源源不断的人来寄包裹,这下,我是真的没有办法啦,该伤的心还是得伤,心有余而力不足,只好拒绝并告知他们另寻他处吧~
当完老板再留恋不舍也要缓过神来呀,再对照上面流程图理解一下线程池吧~核心线程对应到的是3个正式员工,阻塞队列对应到快递小店的存储包裹区,线程池对应到小店的前台(最多能站6个人).
4. 阻塞队列的实现类
1) 数组的实现,指定容量
public ArrayBlockingQueue<>(int capacity){...
2) 链表的实现,无边界或指定容量
public LinkedBlockingQueue<>(){.. //无边界
public LinkedBlockingQueue<>(int capacity){...//指定容量
5. 快捷方式创建线程池
ExecutorService single=Executors.newSingleThreadExecutor();
ExecutorService fixed=Executors.newFixedThreadPool(4);
ExecutorService catched=Executors.newCachedThreadPool();
ScheduledExecutorService scheduled=Executors.newScheduledThreadPool(4);
6. 不能使用快捷方式创建线程池,为什么?
① 阻塞队列都是无边界的,如果提交任务的速度快于执行任务的速度(相当于生产者消费者模型中生产>消费),队列中保存的任务会越来越多,java进程的内存占用越来越多,OOM(内存溢出,java进程挂掉)
② 没有提供拒绝策略,会使用默认的抛异常的方式拒绝.一般来说,任务在线程池无法处理的情况下,也不能直接丢弃,需要记录(一般记录为日志,数据库,其他地方).
7. 4种拒绝策略:
AbortPolicy() //直接抛出异常(默认采用此策略)
CallerRunsPolicy() //只用调用者所在线程来运行任务,即谁让我执行任务/谁提交的任务,就让谁去执行(提交任务的线程)
DiscardPolicy() //丢弃提交的任务
DiscardOldestPolicy() //丢弃队列里最近(最旧)的一个任务,并执行当前任务.
8. 关闭线程池
1) 使用的API
可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池。它们的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程(是否要中断,任务代码自行决定),所以无法响应中断的任务可能永远无法终止。但是它们存在一定的区别。
shutdownNow首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表。
shutdown只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。