阿里编程规范不建议使用线程池,为什么?

什么是线程池?

线程池可以通过池看出来是一个资源集,任何池的作用都大同小异,主要是用来减少资源创建、初始化的系统开销。

创建线程很“贵”吗?

是的。创建线程的代价是昂贵的。

我们都知道系统中的每个进程有自己独立的内存空间,而被称为轻量级进程的线程也是需要的。

在JVM中默认一个线程需要使用256k~1M(取决于32位还是64位操作系统)的内存。(具体的数组我们不深究,因为随着JVM版本的变化这个默认值随时可能发生变更,我们只需要知道线程是需要占用内存的)

除了内存还有更多吗?
许多文章会将上下文切换、CPU调度列入其中,这边不将线程调度列入是因为睡眠中的线程不会被调度(OS控制),如果不是睡眠中的线程那么是一定需要被调度的。
但在JVM中除了创建时的内存消耗,还会给GC带来压力,如果频繁创建线程那么相对的GC的时候也需要回收对应的线程。

线程池的机制?

可以看到线程池是一种重复利用线程的技术,线程池的主要机制就是保留一定的线程数在没有事情做的时候使之睡眠,当有活干的时候拿一个线程去运行。
这些牵扯到线程池实现的具体策略。

阿里开发规范为什么不允许Executors快速创建线程池?

可以看到原因很简单

  1. newSingleThreadExecutor

  2. newFixedThreadPool

在 workQueue 参数直接 使用了 new LinkedBlockingQueue<Runnable>() 理论上可以无限添加任务到线程池。

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

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

如果提交到线程池的任务由问题,比如 sleep 永久,会造成内存泄漏,最终导致OOM。

同时 阿里规范还推荐自定义 threadFactory 设置线程名称便于以后排查问题

更阿里规范总结:

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

1)newFixedThreadPool和newSingleThreadExecutor:

主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。

2)newCachedThreadPool和newScheduledThreadPool:

主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

如果使用Executors的静态方法创建ThreadPoolExecutor对象,可以通过使用Semaphore对任务的执行进行限流也可以避免出现OOM异常

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农乐园

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值