前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >还在用Executors创建线程池?小心内存溢出

还在用Executors创建线程池?小心内存溢出

作者头像
全菜工程师小辉
发布2019-08-16 10:03:36
1.4K0
发布2019-08-16 10:03:36
举报

线程池不建议使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

Executors各个方法的弊端:

  1. newFixedThreadPool 和 newSingleThreadExecutor: 主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。(笔者注:阻塞队列均采用LinkedBlockingQueue)
  2. newCachedThreadPool 和 newScheduledThreadPool: 主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

以上为《阿里巴巴java开发手册》原文


ThreadPoolExecutor函数

Executors提供了四种创建线程池的方法,实际上Executors的底层也是调用了ThreadPoolExecutor。函数定义如下:

public ThreadPoolExecutor(int corePoolSize,  // 线程池的核心线程数
                          int maximumPoolSize, // 线程池的最大线程数
                          long keepAliveTime, // 当线程数大于核心时,多余的空闲线程等待新任务的存活时间。
                          TimeUnit unit, // keepAliveTime的时间单位
                          ThreadFactory threadFactory, // 线程工厂
                          BlockingQueue<Runnable> workQueue,// 用来储存等待执行任务的队列
                          RejectedExecutionHandler handler // 拒绝策略
                          ) 

线程池运行原理:

函数参数补充说明

  1. workQueue有以下七种选择:
  • ArrayBlockingQueue: 一个由数组结构组成的有界阻塞队列(数组结构可配合指针实现一个环形队列)。
  • LinkedBlockingQueue: 一个由链表结构组成的有界阻塞队列,而在未指明容量时,容量默认为Integer.MAX_VALUE。
  • PriorityBlockingQueue: 一个支持优先级排序的无界阻塞队列,对元素没有要求,可以实现Comparable接口也可以提供Comparator来对队列中的元素进行比较,跟时间没有任何关系,仅仅是按照优先级取任务。
  • DelayQueue: 同PriorityBlockingQueue,也是二叉堆实现的优先级主阻塞队列。要求元素都实现Delayed接口,通过执行时延从队列中提取任务,时间没到任务取不出来。
  • SynchronousQueue: 一个不存储元素的阻塞队列,消费者线程调用take()方法的时候就会发生阻塞,直到有一个生产者线程生产了一个元素,消费者线程就可以拿到这个元素并返回;生产者线程调用put()方法的时候就会发生阻塞,直到有一个消费者线程消费了一个元素,生产者才会返回。
  • LinkedTransferQueue: 它是ConcurrentLinkedQueue、LinkedBlockingQueue和SynchronousQueue的结合体,但是把它用在ThreadPoolExecutor中,和LinkedBlockingQueue行为一致。
  • LinkedBlockingDeque: 使用双向队列实现的双端阻塞队列,双端意味着可以像普通队列一样FIFO(先进先出),可以以像栈一样FILO(先进后出)
  1. handler有以下四种取值:
  • AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常。
  • CallerRunsPolicy:由调用线程处理该任务。(例如io操作,线程消费速度没有NIO读取快,可能导致阻塞队列一直增加,此时可以使用这个模式)
  • DiscardPolicy:丢弃任务,但是不抛出异常。 (可以配合这种模式进行自定义的处理方式)
  • DiscardOldestPolicy:丢弃队列最早的未处理任务,然后重新尝试执行任务(重复执行)

可以根据业务场景自定义实现线程工厂,拒绝策略以及阻塞队列。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全菜工程师小辉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ThreadPoolExecutor函数
  • 函数参数补充说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档