线程池解析

目录

一、线程池的概念

二、线程池的作用

三、线程池五种状态

 四、线程池的重要参数

五、拒绝(饱和)策略(四大策略)

1、AbortPolicy(中止策略)-默认

2、DiscardPolicy(丢弃策略)

3、DiscardOldestPolicy(弃老策略)

4、CallerRunsPolicy(调用者运行策略)

六、工作队列

七、线程池工作流程


一、线程池的概念

从字面上理解它就是一个管理线程的池子。

  • 它帮我们管理线程,避免增加创建线程和销毁线程的资源损耗。因为线程其实也是一个对象,创建一个对象,需要经过类加载过程,销毁一个对象,需要走GC垃圾回收流程,都是需要资源开销的。
  • 提高响应速度。 如果任务到达了,相对于从线程池拿线程,重新去创建一条线程执行,速度肯定慢很多。
  • 重复利用。 线程用完,再放回池子,可以达到重复利用的效果,节省资源。

二、线程池的作用

  • 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
  • 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
  • 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
  • 提供更多更强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor,就允许任务延期执行或定期执行

三、线程池五种状态

  • RUNNING线程池一旦被创建,就处于 RUNNING 状态,任务数为 0,能够接收新任务,对已排队的任务进行处理。
  • SHUTDOWN不接收新任务,但能处理已排队的任务。调用线程池的 shutdown() 方法,线程池由 RUNNING 转变为 SHUTDOWN 状态。
  • STOP不接收新任务,不处理已排队的任务,并且会中断正在处理的任务。调用线程池的 shutdownNow() 方法,线程池由(RUNNING 或 SHUTDOWN ) 转变为 STOP 状态。
  • TIDYING
    • SHUTDOWN 状态下,任务数为0, 其他所有任务已终止,线程池会变为 TIDYING 状态,会执行 terminated() 方法。线程池中的 terminated() 方法是空实现,可以重写该方法进行相应的处理。
    • 线程池在 SHUTDOWN 状态,任务队列为空且执行中任务为空,线程池就会由 SHUTDOWN 转变为 TIDYING 状态。
    • 线程池在 STOP 状态,线程池中执行中任务为空时,就会由 STOP 转变为 TIDYING 状态。
  • TERMINATED线程池彻底终止。线程池在 TIDYING 状态执行完 terminated() 方法就会由 TIDYING 转变为 TERMINATED 状态。

 四、线程池的重要参数

  • 核心线程数(corePoolSize):当线程池的线程都忙碌时,再进来新任务时,由最小线程数扩容到核心线程数 。一般设置为cpu的核数
  • 最大线程数 (maximumPoolSize):当核心线程数满了,当队列也满了,再来新任务,就会创建新非核心线程来执行这个新任务,直到线程数达到最大线程数。一般设置为cpu的核数*2
  • 存活时间(keepAliveTime):非核心线程 =(maximumPoolSize - corePoolSize ) ,非核心线程闲置下来不干活最多存活时间。当非核心线程超过多长时间不执行任务,处于空闲状态,线程池会将它回收,直到线程数量达到核心线程数。如果设置为0,就代表不回收
  • 存活时间单位(unit):线程池中非核心线程保持存活的时间的单位

TimeUnit.DAYS; 天
TimeUnit.HOURS; 小时
TimeUnit.MINUTES; 分钟
TimeUnit.SECONDS; 秒
TimeUnit.MILLISECONDS; 毫秒
TimeUnit.MICROSECONDS; 微秒
TimeUnit.NANOSECONDS; 纳秒

  • 线程池等待队列(workQueue):维护着等待执行的Runnable对象。当运行当线程数= corePoolSize时,新的任务会被添加到workQueue中,如果workQueue也满了则尝试用非核心线程执行任务,等待队列应该尽量用有界的。
  • threadFactory

        创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等。

  • handler

        corePoolSize、workQueue、maximumPoolSize都不可用的时候执行的饱和策略。

五、拒绝(饱和)策略(四大策略)

1、AbortPolicy(中止策略)-默认

  • 功能:当触发拒绝策略时,直接抛出拒绝执行的异常
  • 使用场景:ThreadPoolExecutor中默认的策略就是AbortPolicy,由于ExecutorService接口的系列ThreadPoolExecutor都没有显示的设置拒绝策略,所以默认的都是这个。

2、DiscardPolicy(丢弃策略)

  • 功能:直接丢弃这个任务,不触发任何动作
  • 使用场景: 提交的任务无关紧要,一般用的少。

3、DiscardOldestPolicy(弃老策略)

  • 功能:抛弃下一个将要被执行的任务,相当于排队的时候把第一个人打死,然后自己代替
  • 使用场景:发布消息、修改消息类似场景。当老消息还未执行,此时新的消息又来了,这时未执行的消息的版本比现在提交的消息版本要低就可以被丢弃了。

4、CallerRunsPolicy(调用者运行策略)

  • 功能:只要线程池没有关闭,就由提交任务的当前线程处理
  • 使用场景:一般在不允许失败、对性能要求不高、并发量较小的场景下使用。

一般情况下,前三种都会有丢弃任务的风险,但是性能都比较好,第4种最稳妥。

六、工作队列

  • ArrayBlockingQueue:使用数组实现的有界阻塞队列,特性先进先出
  • LinkedBlockingQueue:使用链表实现的阻塞队列,特性先进先出,可以设置其容量,默认为Interger.MAX_VALUE
  • PriorityBlockingQueue:使用平衡二叉树堆,实现的具有优先级的无界阻塞队列
  • DelayQueue:无界阻塞延迟队列,队列中每个元素均有过期时间,当从队列获取元素时,只有过期元素才会出队列。队列头元素是最块要过期的元素。
  • SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作,必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态

七、线程池工作流程

判断线程池里的核心线程是否都在执行任务?

  • 否:调用/创建一个新的核心线程来执行任务
  • 是:工作队列是否已满?
    • 否:将新提交的任务存储在工作队列里
    • 是:线程池里的线程数是否达到最大线程值?
      • 否:调用/创建一个新的非核心线程来执行任务
      • 是:执行线程池饱和策略

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值