线程池
线程池
DreamCollector一、线程池构建
有参构造:
1 | /* |
1 | //自定义线程池例子: |
二、常用线程池
newFixedThreadPool(固定数目线程的线程池)
FixedThreadPool 适用于处理CPU密集型的任务,确保CPU在长期被工作线程使用的情况下,尽可能的少的分配线程,即适用执行长期的任务。
newCachedThreadPool(可缓存线程的线程池)
当提交任务的速度大于处理任务的速度时,每次提交一个任务,就必然会创建一个线程。极端情况下会创建过多的线程,耗尽 CPU 和内存资源。由于空闲 60 秒的线程会被终止,长时间保持空闲的CachedThreadPool 不会占用任何资源)
newSingleThreadExecutor(单线程的线程池)
适用于串行执行任务的场景,一个任务一个任务地执行
newScheduledThreadPool(定时及周期执行的线程池)
周期性执行任务的场景,需要限制线程数量的场景
三、执行流程
理论上:提交的任务数>(maxPoolSize+queueCapacity)时就会触发绝绝策略
四、阻塞队列
实现了BlockingQueue接口的类:
阻塞队列 | 描述 | 是否有界 |
---|---|---|
ArrayBlockingQueue | 基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。 | 是 |
LinkedBlockingQueue | 基于链表结构的有界阻塞队列,此队列按 FIFO 排序元素,吞吐量通常要高于 ArrayBlockingQueue且界限默认大小为Integer.MAX_Value(2^31-1),值非常大,相当于无界 | 是 |
LinkedBlockingDeque | 基于链表结构的双向有界阻塞队列 | 是 |
LinkedTransferQueue | 基于链表组成的无界阻塞传输队列 | 否 |
SynchronousQueue | 一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于 LinkedBlockingQueue | 是 |
DelayQueue | 使用优先级队列实现的延迟无界阻塞队列 | 否 |
五、拒绝策略
默认拒绝策略为AbortPolicy
拒绝策略 | 描述 |
---|---|
AbortPolicy | 这种拒绝策略在拒绝任务时,会直接抛出异常 RejectedExecutionException (属于RuntimeException),让你感知到任务被拒绝了,于是你便可以根据业务逻辑选择重试或者放弃提交等策略 |
DiscardPolicy | 这种拒绝策略当新任务被提交后直接被丢弃掉,也不会给你任何的通知,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失 |
DiscardOldestPolicy | 如果线程池没被关闭且没有能力执行,则会丢弃任务队列中的头结点,通常是存活时间最长的任务,这种策略与第二种不同之处在于它丢弃的不是最新提交的,而是队列中存活时间最长的,这样就可以腾出空间给新提交的任务,但同理它也存在一定的数据丢失风险 |
CallerRunsPolicy | 当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交于提交任务的线程执行,也就是谁提交任务,谁就负责执行任务。这样做主要有两点好处(1.新提交的任务不会被丢弃,这样也就不会造成业务损失。2.由于谁提交任务谁就要负责执行任务,这样提交任务的线程就得负责执行任务,而执行任务又是比较耗时的,在这段期间,提交任务的线程被占用,也就不会再提交新的任务,减缓了任务提交的速度,相当于是一个负反馈。在此期间,线程池中的线程也可以充分利用这段时间来执行掉一部分任务,腾出一定的空间,相当于是给了线程池一定的缓冲期) |
六、线程调优
最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果