17

被开发者抛弃的 Executors,错在哪儿?

 5 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzIxNjc0ODExMA%3D%3D&%3Bmid=2247486594&%3Bidx=1&%3Bsn=ec03c49c2ea22925bbb83828bcc8a540
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
uaQZfmN.jpg!webiQFrYfu.jpg!web

一. 序

在 Java 领域内,我们使用多线程的方式来实现并发编程。而线程本身是操作系统的一个概念,虽然不同的语言对线程都进行了一些封装,但是最终都是调用到操作系统中去创建和调度线程。

既然线程是一项重要的系统资源,为了更合理的利用此资源,我们会使用池化技术来优化线程的创建和销毁,这就是 线程池

在我们学习并发编程的时候,线程可以利用 Thread 来创建并通过 start() 来启动一个线,但在成熟的项目中,基本上是不允许这样操作线程的,都需要通过线程池去收敛线程的使用,所以线程池是必须的。

Java 的线程池可以通过 ThreadPoolExecutor 来构造,在其中提供非常完备的构造方法,可以根据我们的业务需求灵活的构造线程池。同时 Java 还提供了一个 Executors,它内部提供了很多包装的方法,利用它可以帮我们快速的构建线程池。

原本 Executors 的目的就是为了让我们更方便的使用线程池,但是《阿里巴巴Java开发手册》也明确指出,直接使用 Executors 的缺陷。

手册中提到强制不允许使用 Executors 去创建线程池,而是应该使用退化到最原始的 ThreadPoolExecutor 的方式。

quErIr3.jpg!web

日常开发中,应该收紧对线程池的创建,由开发人员明确线程池的运行规则,以此来尽量规避其资源耗尽的风险。

线程池是个好东西,但是怎么创建是一个问题。

二. Executors 怎么了?

2.1 不被允许的 Executors

不应该使用 Executors 的原因,其实《阿里巴巴Java开发手册》里已经写明了,当需要处理大量任务的时候,可能会出现 OOM 异常,但它们出现 OOM 的原因并不一样。

ThreadPoolExecutor 的构造方法中,提供了很多参数的配置,其中与 Executors 出现 OOM 相关的就有 2 个: 核心线程数等待队列

先来看看 FixedThreadPool 和 SingleThreadPool 出现 OOM 的原因。

它们的问题在于等待队列使用了 LinkedBlockingQueue 这个以链表实现的无界队列( 最大长度是 Integer.MAX_VALUE ),最终导致堆积了大量等待处理的任务,从而导致频繁的 GC,最终触发 OOM。

java.lang.OutOfMemoryError: GC overhead limit exceeded

再来看看 CachedThreadPool 出现 OOM 的原因。

它的问题在于核心线程数设置为了 Integer.MAX_VALUE,并且等待队列是一个 SynchronousQueue。

SynchronousQueue 是一个没有数据缓冲的阻塞队列,它极易被阻塞。在等待队列被阻塞的时候,如果线程数量还没有达到核心线程数限制的数量时,线程池的策略是创建新的线程来处理新的任务。

也就是说,是核心线程数和等待队列 SynchronousQueue 合力造成了线程会跟随任务不断的被创建,直到触发 OOM。

java.lang.OutOfMemoryError: pthread_creat (1040KB stack) failed: Try again

ScheduledThreadPool 的等待队列使用的是 DelayedWorkQueue,原理也是类似的,最终会导致创建大量的线程而抛出 OOM。

线程是一种系统资源,本身创建就会带来内存开销,同时操作系统对单进程可创建的线程数也是有限制的。

在 Android 中,每个线程初始化都需要 mmap 一定的堆内存,在默认的情况下,初始化一个线程大约需要 mmap 1MB 左右的内存空间。同时系统本身也会对每个进程可创建的线程数,做一定的限制,这个限制在 /proc/pid/limits 中,不同的厂商对这个限制也有所不同,当超出限制时,哪怕堆上还有可用内存,依然会抛出 OOM。

2.2 Executors 错在哪儿了?

Executors 会在任务过多的时候,导致资源耗尽而触发 OOM,这是它带来的危害。

Executors 最大的问题,在于没有边界。

在系统环境良好,任务不多的时候 Executors 创建的线程池,都是可以正常工作的。

但是一旦有重压,我们就无法预知什么时候会出现问题,这就是没有边界,没有边界就意味着不可控。

我们很难去信任一段不可控的代码,它什么时候出现问题,完全是不可预知的,这才是 Executors 最大的问题。

除此之外,Executors 封装了太多线程池的细节,本身也不建议使用。例如通常我们需要給线程池创建的线程,起一个有意义的名称,方便在出现异常的时候排查问题;再例如对于线程池的拒绝策略,我们需要深思熟虑的定义,是直接抛弃还是持久化下来延迟处理。

去思考一个线程池的不同参数带来的策略细节,才是使用线程池的一个良好的开发习惯。

三. 小结时刻

本文我们聊了关于创建线程池,使用 Executors 创建的线程池会有 OOM 的风险,应该使用 ThreadPoolExecutor 去创建线程池。通过思考业务来明确配置线程池不同的参数,例如线程池、等待队列、拒绝策略等等。

今天就到这里,有任何问题,欢迎留言讨论。

本文对你有帮助吗? 留言、转发、点好看 是最大的支持,谢谢!

公众号后台回复成长『 成长 』,将会得到我准备的学习资料。

UJzIVrY.png!web

bInEraB.jpg!web

3EzeErq.jpg!web

nUfERf7.jpg!web

Recommend

  • 61
    • www.jisilu.cn 7 years ago
    • Cache

    刘主席到底错在了哪里

    刘主席到底错在了哪里 - 倡导价值投资没有问题,打击投机炒作也没问题。但是一昧的使用行政手段、而非市场的力量强制调节市场,往往会得到适得其反的效果。本来活跃的市场是需要适度投机的。一度打压投机,反而把整个一体化的市场极度分裂,搞的整个市场不伦不类!...

  • 49
    • www.tuicool.com 6 years ago
    • Cache

    A Short Detour: Executors

    A few weeks ago, the member of the C++ standardisation committee Felix Petriconi wrote me an E-Mail. He said my article about std::future Extensions

  • 44

    腾讯必须得有点破釜沉舟的勇气了。

  • 54

    Executors是一个线程池的工厂类,提供各种有用的线程池的创建,使用得当,将会使我们并发编程变得简单!今天就来聊聊这个工厂类的艺术吧! Executors只是Executor框架的主要成员组件之一,为java的异步任务调度执行提供了重要的...

  • 32

    一转眼

  • 33
    • 新浪科技 tech.sina.com.cn 5 years ago
    • Cache

    蔚来错在哪儿?

    文/张博文成为明星创业公司,意味着你会有大量的人关注,同时也意味着几乎你每一点动态,都会暴露在阳光下,供人议论。前两周蔚来风波不断,主要原因在于裁员,经过了多次消息曝光和官方辟谣,蔚来在周末办了场媒体活动,除了裁员,还谈了一些关乎企业生存的

  • 41

    看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,通过源码分析禁用的原因 写在前面 首先感谢大家在盖楼的间隙阅读本篇文章,通过阅读本篇文章你将了解到: 线程池的定义 Exec

  • 7

    导读 在语音机器人中,经常需要槽位识别来提取用户回答中的关键信息,以便用于控制对话逻辑跳转和标识对话关键词等,我们通过命名实体识别(Named Entity Recognition,NER)技术来提取对话中的实体词(关键词),即语...

  • 8
    • finance.sina.com.cn 4 years ago
    • Cache

    炫富的大LOGO们,错在哪儿?

    炫富的大LOGO们,错在哪儿? 2021-04-20 13:40:37...

  • 6

    汽车 小米汽车售价14.99万?博主称是被暗害,小米王化:错在小爱同学 电科技袁创06-27 16:17 142 近日,一条有关小米...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK