⾃定义线程池拒绝策略及有界⽆界队列⼀、拒绝策略
1、⾃定义线程池的参数说明
2、详细说明
核⼼线程数:实际运⾏的线程数
最⼤线程数:最⼤可以创建的线程数
3、jdk⾃带的四种策略
(1)ThreadPoolExecutor.AbortPolicy 丢弃任务,并抛出 RejectedExecutionException 异常。
(2)ThreadPoolExecutor.CallerRunsPolicy:该任务被线程池拒绝,由调⽤ execute⽅法的线程执⾏该任务。(3)ThreadPoolExecutor.DiscardOldestPolicy : 抛弃队列最前⾯的任务,然后重新尝试执⾏任务。
(4)ThreadPoolExecutor.DiscardPolicy,丢弃任务,不过也不抛出异常。
当线程池的任务缓存队列已满并且线程池中的线程数⽬达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略。
4、Threa dPo o lExec uto r处理任务的顺序、原理
4、Thr ea
⼀个任务通过 execute(Runnable) ⽅法被添加到线程池,任务就是⼀个 Runnable 类型的对象,任务的执⾏⽅法就是 Runnable 类型对象的run() ⽅法。
当⼀个任务通过 execute(Runnable) ⽅法欲添加到线程池时,线程池采⽤的策略如下(即添加任务的策略):
如果此时线程池中的数量⼩于 corePoolSize ,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize ,但是缓冲队列 workQueue 未满,那么任务被放⼊缓冲队列。
如果此时线程池中的数量⼤于 corePoolSize ,缓冲队列 workQueue 满,并且线程池中的数量⼩于maximumPoolSize ,建新的线程来处理被添加的任务。
如果此时线程池中的数量⼤于 corePoolSize ,缓冲队列 workQueue 满,并且线程池中的数量等于maximumPoolSize ,那么通过 handler 所指定的策略来处理此任务。
任务处理的优先级(顺序)为:
核⼼线程 corePoolSize 、任务队列 workQueue 、最⼤线程 maximumPoolSize ,如果三者都满了,使⽤ handler处理被拒绝的任务。当线程池中的线程数量⼤于 corePoolSize 时,如果某线程空闲时间超过 keepAliveTime ,线程将被终⽌。这样,线程池可以动态的调整池中的线程数。
⼆、队列
从有界⽆界上分
常见的有界队列为
ArrayBlockingQueue 基于数组实现的阻塞队列
LinkedBlockingQueue 其实也是有界队列,但是不设置⼤⼩时就是⽆界的。
ArrayBlockingQueue 与 LinkedBlockingQueue 对⽐⼀哈
ArrayBlockingQueue 实现简单,表现稳定,添加和删除使⽤同⼀个锁,通常性能不如后者
LinkedBlockingQueue 添加和删除两把锁是分开的,所以竞争会⼩⼀些
SynchronousQueue ⽐较奇葩,内部容量为零,适⽤于元素数量少的场景,尤其特别适合做交换数据
⽤,内部使⽤ 队列来实现公平性的调度,使⽤栈来实现⾮公平的调度,在Java6时替换了原来的锁逻辑,使⽤CAS代替了
上⾯三个队列他们也是存在共性的
put take 操作都是阻塞的
offer poll 操作不是阻塞的,offer 队列满了会返回false不会阻塞,poll 队列为空时会返回null不会阻塞
补充⼀点,并不是在所有场景下,⾮阻塞都是好的,阻塞代表着不占⽤CPU,在有些场景也是需要阻塞的,put take 存在必有其存在的必然性java线程池创建的四种
常见的⽆界队列
ConcurrentLinkedQueue ⽆锁队列,底层使⽤CAS操作,通常具有较⾼吞吐量,但是具有读性能的不确定性,弱⼀致性——不存在如ArrayList等集合类的并发修改异常,通俗的说就是遍历时修改不会抛异常
PriorityBlockingQueue 具有优先级的阻塞队列
DelayedQueue 延时队列,使⽤场景
缓存:清掉缓存中超时的缓存数据
任务超时处理
补充:内部实现其实是采⽤带时间的优先队列,可重⼊锁,优化阻塞通知的线程元素leader
LinkedTransferQueue 简单的说也是进⾏线程间数据交换的利器,在SynchronousQueue 中就有所体现,并且并发⼤神 Doug Lea 对其进⾏了极致的优化,使⽤15个对象填充,加上本⾝4字节,总共64字节就可以避免缓存⾏中的伪共享问题,其实现细节较为复杂,可以说⼀下⼤致过程:
⽐如消费者线程从⼀个队列中取元素,发现队列为空,他就⽣成⼀个空元素放⼊队列 , 所谓空元素就是数据项字段为空。然后消费者线程在这个字段上旅转等待。这叫保留。直到⼀个⽣产者线程意欲向队例中放⼊⼀个元素,这⾥他发现最前⾯的元素的数据项字段为 NULL,他就直接把⾃已数据填充到这个元素中,即完成了元素的传送。⼤体是这个意思,这种⽅式优美了完成了线程之间的⾼效协作。参考⾃
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论