编程知识 cdmana.com

Java中的线程池

为什么使用线程池?

  • 反复创建线程开销较大
  • 过多的线程会占用太多的内存

使用线程池的优点:

  • 降低资源消耗(重复利用已创建的线程)
  • 提高响应速度
  • 集中控制

线程池的创建:

new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,workQueue,threadFactory,Handler);

参数意义:

  • corePoolSize 核心线程数:如果当前运行的线程小于corePoolSize时,则创建新线程来执行任务
  • 如果运行的线程等于或大于corePoolSize 则将任务加入队列
  • 如果队列已满,则创建新的线程,线程总数不能超过 maximumPoolSize
  • 如果队列已满,且线程数大于或等于maximumPoolSize 则拒绝任务
  • keepAliveTime 超时时间:如果线程数多于corePoolSize,那么如果多余的线程空闲时间超过keepAliveTime ,他们就会被终止

巧妙设置参数

  • 通过设置corePoolSize与maximumPoolSize相同,可以设置固定大小的线程池
  • 通过设置maximumPoolSize为很高的值,例如Ingteger.MAX _VALUE,在理论上可以允许线程池可以容纳任意数量的并发任务
  • 只有在队列填满时才创建多于corePoolSize的线程,所以如果使用的是无界队列(例如LinkedBlockingQueue),那么线程数不会超过corePoolSize

工作队列

  • ArrayBlockingQueue:一个基于数组结构的有界阻塞队列,此队列按照先进先出原则对元素进行排序
  • LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按照先进先出原则对元素进行排序。吞吐量高于ArrayBlockingQueue
  • SynchronusQueue:一个不存储元素的阻塞队列。吞吐量高于LinkedBlockingQueue
  • PriorityBlockingQueue:一个具有优先级的无限阻塞队列

Executor框架

Executors可以创建3种类型的线程池

  • FixedThreadPool:适用于为了满足资源管理的需求,而需要限制线程数量的应用场景。内部工作队列为LinkedBlockingQueue,容量为Integer.MAX_VALUE. 所以当请求越来越多,而且无法及时处理完毕时,也就是请求堆积时,会容易造成占用大量的内存,可能导致OOM
  • SingleThreadExecutor:固定容量为1的线程池。适用于保证顺序执行各个任务,并且在任意时间内,不会有多线程是活动的。内部工作队列也为LinkedBlockingQueue,故缺点也与上述相同
  • CachedThreadPool:适用于执行很多短期异步任务的小程序,或者是负载较轻的服务器。最大线程数为Integer.MAX_VALUE,这可能会导致创建数量非常多的线程
  • ScheduledThreadPool 支持周期性的任务执行的线程池

线程池中的线程数目设定为多少比较合适?

  • CPU密集型(加密、计算hash等):最佳线程数为CPU核心数的1-2倍左右
  • 耗时IO型(读写数据库、文件、网络读写等):最佳线程数一般会大于CPU核心数很多倍,以JVM线程监控显示繁忙情况为依据,保证线程空闲可以衔接上。
  • 线程数=CPU核心数*(1+平均等待时间/平均工作时间)

线程池状态

  • RUNNING:接受新任务并处理排队任务
  • SHUTDOWN:不接受新任务,但处理排队任务
  • STOP:不接受新任务,也不处理排队任务,并中断正在运行的任务
  • TIDYING:所有的任务 都已终止,线程会转换到TIDYING状态,并将运行terminate() 钩子方法
  • TERMINATED:terminate()运行完成

线程池的操作

execte:提交任务
shutdown 停止线程
IsShutdown 检测是否执行了shutdown方法
IsTerminated 检测线程是否完全停止
AwatitTermination:检测一段时间内线程是否完全终止
ShutdownNow:关闭所有线程(为执行中的线程执行interrupt通知,并将队列中未执行完毕的线程存入返回的List数组中)

拒绝任务

拒绝时机

  • 当Executor关闭时,提交新任务会被拒绝
  • 当Executor 的线程容量和工作队列已经饱和时

拒绝策略

  • AbortPolicy 拒绝并返回错误信息
  • DiscardPolicy 偷摸拒绝 不返回错误信
  • DiscardOldestPolicy 拒绝队列中最老的任
  • CallerRunsPolicy 将该任务抛给主线程执行

线程池的组成部分

  • 线程池管理器
  • 工作队列
  • 任务队列
  • 任务接口

使用线程池的注意点

  • 避免任务堆积
  • 避免线程数过度增加
  • 排查线程泄露

版权声明
本文为[ordinaryBlog]所创,转载请带上原文链接,感谢
https://blog.csdn.net/kang2411212/article/details/120132957

Scroll to Top