加入收藏 | 设为首页 | 会员中心 | 我要投稿 河北网 (https://www.hebeiwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

为什么阿里要禁用 Executors 建设线程池?

发布时间:2019-11-14 03:00:23 所属栏目:建站 来源:佚名
导读:【线上直播】11月21日晚8点贝壳技能总监侯圣文《数据安详之数据库安详黄金法例》 看阿里巴巴开拓手册并发编程这块有一条:线程池不应承行使Executors去建设,而是通过ThreadPoolExecutor的方法,通过源码说明禁用的缘故起因。 写在前面 起首感激各人在盖楼的间

CachedThreadPool是一个按照必要建设新线程的线程池

  • corePoolSize => 0,焦点线程池的数目为0
  • maximumPoolSize => Integer.MAX_VALUE,可以以为最大线程数是无穷的
  • keepAliveTime => 60L
  • unit => 秒
  • workQueue => SynchronousQueue

当一个使命提交时,corePoolSize为0不建设焦点线程,SynchronousQueue是一个不存储元素的行列,可以领略为队里永久是满的,因此最终会建设非焦点线程来执利用命。

对付非焦点线程空闲60s时将被接纳。由于Integer.MAX_VALUE很是大,可以以为是可以无穷建设线程的,在资源有限的环境下轻易引起OOM非常

Executors#newSingleThreadExecutor要领

  1. public static ExecutorService newSingleThreadExecutor() { 
  2.     return new FinalizableDelegatedExecutorService 
  3.         (new ThreadPoolExecutor(1, 1, 
  4.                                 0L, TimeUnit.MILLISECONDS, 
  5.                                 new LinkedBlockingQueue<Runnable>())); 

SingleThreadExecutor是单线程线程池,只有一个焦点线程

  • corePoolSize => 1,焦点线程池的数目为1
  • maximumPoolSize => 1,只可以建设一个非焦点线程
  • keepAliveTime => 0L
  • unit => 秒
  • workQueue => LinkedBlockingQueue

当一个使命提交时,起首会建设一个焦点线程来执利用命,假如高出焦点线程的数目,将会放入行列中,由于LinkedBlockingQueue是长度为Integer.MAX_VALUE的行列,可以以为是无界行列,因此往行列中可以插入无穷多的使命,在资源有限的时辰轻易引起OOM非常,同时由于无界行列,maximumPoolSize和keepAliveTime参数将无效,压根就不会建设非焦点线程

Executors#newFixedThreadPool要领

  1. public static ExecutorService newFixedThreadPool(int nThreads) { 
  2.     return new ThreadPoolExecutor(nThreads, nThreads, 
  3.                                   0L, TimeUnit.MILLISECONDS, 
  4.                                   new LinkedBlockingQueue<Runnable>()); 

FixedThreadPool是牢靠焦点线程的线程池,牢靠焦点线程数由用户传入

  • corePoolSize => 1,焦点线程池的数目为1
  • maximumPoolSize => 1,只可以建设一个非焦点线程
  • keepAliveTime => 0L
  • unit => 秒
  • workQueue => LinkedBlockingQueue
  • 它和SingleThreadExecutor相同,独一的区别就是焦点线程数差异,而且因为行使的是LinkedBlockingQueue,在资源有限的时辰轻易引起OOM非常

总结:

  • FixedThreadPool和SingleThreadExecutor => 应承的哀求行列长度为Integer.MAX_VALUE,也许会会萃大量的哀求,从而引起OOM非常
  • CachedThreadPool => 应承建设的线程数为Integer.MAX_VALUE,也许会建设大量的线程,从而引起OOM非常

这就是为什么榨取行使Executors去建设线程池,而是保举本身去建设ThreadPoolExecutor的缘故起因

OOM非常测试

理论上会呈现OOM非常,必需测试一波验证之前的说法:

测试类:TaskTest.java

  1. public class TaskTest { 
  2.     public static void main(String[] args) { 
  3.         ExecutorService es = Executors.newCachedThreadPool(); 
  4.         int i = 0; 
  5.         while (true) { 
  6.             es.submit(new Task(i++)); 
  7.         } 
  8.     } 

行使Executors建设的CachedThreadPool,往线程池中无穷添加线程

在启动测试类之前先将JVM内存调解小一点,否则很轻易将电脑跑出题目【别问我为什么知道,是铁憨憨甜没错了!!!】,在idea里:Run -> Edit Configurations

为什么阿里要禁用 Executors 建设线程池?

JVM参数声名:

  • -Xms10M => Java Heap内存初始化值
  • -Xmx10M => Java Heap内存最大值

运行功效:

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"Disconnected from the target VM, address: '127.0.0.1:60416', transport: 'socket'

建设到3w多个线程的时辰开始报OOM错误

其它两个线程池就不做测试了,测试要领同等,只是建设的线程池纷歧样

怎样界说线程池参数

CPU麋集型 => 线程池的巨细保举为CPU数目 + 1,CPU数目可以按照Runtime.availableProcessors要领获取

IO麋集型 => CPU数目 * CPU操作率 * (1 + 线程守候时刻/线程CPU时刻)

殽杂型 => 将使命分为CPU麋集型和IO麋集型,然后别离行使差异的线程池行止理赏罚,从而使每个线程池可以按照各自的事变负载来调解

阻塞行列 => 保举行使有界行列,有界行列有助于停止资源耗尽的环境产生

(编辑:河北网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读