多线程-生产者消费者问题、线程池
(—接上篇《多线程-线程的生命周期、线程同步与死锁》的完善)
一、线程池工作原理步骤
步骤:
- 核心线程池,声明时预估的数量,池内数量的线程同时进行执行,如果没满则新建一个线程处理刚提交来的任务,若池内线程全部在执行任务,进入下一步。
- 阻塞队列,核心线程池满了后再有线程会判断阻塞队列是否满了,阻塞队列没满就将任务放入阻塞队列中,没满就进入下一步。
- 线程池,判断线程池中所有的线程是否都在执行任务,若没有则创建线程,否则交给饱和策略处理
二、线程池的分类
-
ThreadPoolExecutor(声明方式:ExeCutors.以下3种)
声明:
newCachedThreadPool()
newFixedThreadPool(nThreads)
newSingleThreadExecutor() 【单个线程】
上面三种的源码都是基于ThreadPoolExecutor -
ScheduledThreadPoolExecutor (声明方式:ExeCutors.以下2种)
Scheduled代表可调度的
声明:
newSingleThreadScheduledExecutor
newScheduledThreadPool(corePoolSize)
上面三种的源码都是基于ScheduledThreadPoolExecutor -
ForkJoinPool(分而治之,分组)
声明:
newWorkStealingPool
三、线程池的生命周期(2个状态,其他为中间过度状态)
running -> shutdown/stop -> tidying -> terminated
-
运行状态(running)
-
终止状态(terminated)
声明流程:
从running->terminated之间有shutdown、stop、tidying三个过渡状态。
running调用shutdown()进入shutdown状态
running调用shutdownNow()进入stop状态
从shutdown -> tidying (流程解释:不再接收新任务,当前执行的任务结束后,而且队列为空,才会进入tidying收回)
从stop -> tidying (流程解释:不再接收新任务,当前任务无论是否结束,阻塞队列中是否有任务,直接进入tidying全部回收)
tidying调用terminated()进入terminated状态 (流程解释:若所有的任务都终止了,有效线程数为0,线程池会调用terminated()进入terminated状态)
至此线程池的生命周期结束。
四、线程池的创建
- 七个参数含义:
①:corePoolSize:核心线程池大小,线程的标准数量(常量恒定值)
②:maximumPoolSize:最大容纳线程数量(池子的最大上限)
③:keepAliveTime:存活时间
④:timeUnit:存活时间单位
⑤:blockingQueque:阻塞队列,共享资源的等待和唤醒 ⑥:threadFactory:线程工厂
⑦:rejectedExecutionHandler:饱和策略
五、阻塞队列
-
ArrayBlockingQueue(基于数组的阻塞队列)
-
LinkedBlockingQueue(基于链表的阻塞队列)
-
DelayQueue(只有当其指定的延迟时间到了才能从队列中获取元素)
-
PriorityBlockingQueue(基于优先级的阻塞队列,优先级的判断是通过构造函数传入的compator对象来决定)
-
SynchronousQueue(同步阻塞队列)
面试题:ArrayBlockingQueue和LinkedBlockingQueue区别:
六、拒绝策略
(第四种的意思为如果当前队列满了,又来一个任务,先执行这个新任务,队列继续阻塞不动)