线程池基本概念不清楚的请移步:第一篇:Java中的线程池介绍(阿里为什么要禁用Java内置线程池?自定义线程池参数如何设置?)-CSDN博客
Java中为我们提供了内置线程池,为什么阿里却要严令禁止使用呢?
一、阿里为什么要禁用Java内置线程池?
我们首先看一下阿里开发手册如何说明的:
第一点:在代码中,阿里要求,所有项目开发者都不要自己去手动创建线程而是去线程池中获取线程资源,避免频繁创建线程带来资源消耗,同时可以避免并发场景下创建大量线程而导致内存溢出的问题。
第二点:为什么不让使用Java内置的线程池而是通过ThreadPoolExecuter,也就是自定义线程池的方式来创建线程池?
主要就是因为Java内置的线程池都是创建固定的线程数量或者工作队列数量,当在并发场景下时,就会导致我们系统资源耗尽,造成内存溢出(OOM)问题。
再一个就是,线程池的线程数,工作队列数其实也和我们当前部署的机器的性能有关系,线程池的设置存在极强的环境要求,不同环境下,不同项目需求,对我们的线程池要求都是不一样的,不能一概而论,因此阿里严禁使用Java内置线程池,要求自定义线程池。
二、既然不让使用内置线程池,自定义线程池时,参数的设置有什么讲究吗?
有!讲究非常大!
自定义线程池时,我们通常从两方面考虑
- 服务器性能
- 业务需求
服务器性能:这个其实很好理解,cpu越多,当前机器性能越好,设置线程数也就可以越多。
最主要的是对业务需求的划分来制定参数设置:
- 计算密集型应用:对于CPU密集型业务来说,它的特点是要进行大量的CPU计算,比如计算高等数学中学习的泰勒公式,就会非常消耗我们的CPU资源。这种CPU密集型业务虽然也可以拆成多个任务去执行,但是任务越多,切换的成本就越大。所以,我们就要最高效地利用CPU,遇到CPU密集型的业务场景时,我们需要让同时执行的任务数量等于CPU的核数。
- IO密集型应用:涉及IO操作的场景,比如包括网络IO和磁盘IO,一般都是IO密集型的业务。
在这类场景下,CPU消耗极小,程序大部分时间都被IO操作阻塞。对于IO密集型场
景,显然线程越多,CPU利用率越高,当然也要注意线程别太多,否则也会出现资源耗尽
的问题。我们工作中遇到的大部分场景,都需要和磁盘、网络打交道,都属于IO密集
型。
对于IO密集型应用,如何设置?
公式:线程数 = cpu核心数 / (1 - 阻塞系数)
cpu核心数:当前服务器cpu核心有多少个
阻塞系数:对于阻塞系数,我们可以先试着猜测,或者采用一些性能分析工具(Jmater)来确定线程花在系统IO操作上的时间与CPU密集任务所耗的时间比值,常见数值约为0.7~0.9之间。
如果任务计算时90%的时间双核CPU都在闲置,线程则应设置为20
如果任务计算时50%的时间双核CPU都在闲置,线程则应设置为4
对于计算密集型的任务,如何设置?
很简单,线程数 = N + 1 N代表cpu核心数 ,为什么要加一,多提供一个线程来执行上行文调度这种辅助操作。