自定义线程池与非自定义线程池值的设计

通过观察Java中的内置线程池参数和线程池工作流程总结,从而发现要设计好一个好的线程池,就必须合理的设置线程池的4个参数
1、核心线程数(corePoolSize)
    核心线程数的设计需要根据“任务的处理时间”和“每秒产生的任务数量”来确定。
    例如执行一个任务需要0.1秒,系统百分之80的时间每秒会产生100个任务,那么要想在1秒内处理完这100个任务,就需要10个线程,此时我们可以
确定将核心线程数设计为10;当然实际情况不可能这么平均,所以我们一般按照8020原则设计即可,即按照百分之80的情况设计核心线程数,剩下的百分之20可以利用最大线程数处理。

2、任务队列长度(workQueue)
    任务队列的长度一般设计为:核心线程数/单个任务执行时间*2即可,例如上面的场景中,核心线程数设计为10,单个任务执行时间为0.1秒,则队列长度可以设置为200;

3、最大线程数(maximumPoolSize)
    最大线程数的设计除了参照核心线程数的条件外,还可以参考系统中每秒产生的最大任务数决定。例如上述环境中,如果系统每秒最大产生的任务是1000个,
那么最大线程数=(最大任务数-任务队列长度)*单个任务执行时间:即最大线程数=(1000-200)*0.1=80个

4、最大空闲时间(keepAliveTime)
    这个参数的设计完全参考系统运行环境和硬件压力设定,没有固定的参考值,用户可以根据经验和系统产生任务的时间间隔合理设置一个值即可。

注:上面参数的设置只是一般的设计原则,并不是固定的,用户可以根据实际情况灵活调整。

而对于非自定义线程池的值的设计:
几种常见的线程池:
    newFixedThreadPool(固定大小的线程池)
        创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
        定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
    newSingleThreadExecutor(单线程线程池)
        创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
    newCachedThreadPool(可缓存线程的线程池)
        创建一个可缓存线程池,先查看池中有没有以前建立的线程,如果有,就直接使用。如果没有,就建一个新的线程加入池中,缓存型池子通常用于执行一些生存期很短的异步型任务
    newScheduledThreadPool
        创建一个定长线程池,支持定时及周期性任务执行。

关于线程池取值的大小为:
一般说来,大家认为线程池的大小经验值应该这样设置:(其中N为CPU的个数)
    如果是CPU密集型应用,则线程池大小设置为N+1
    如果是IO密集型应用,则线程池大小设置为2N+1
    如果一台服务器上只部署这一个应用并且只有这一个线程池,那么这种估算或许合理,具体还需自行测试验证。
    但是,IO优化中,这样的估算公式可能更适合:
        最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目
    因为很显然,线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。
    下面举个例子:
    比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,那么根据上面这个公式估算得到:((0.5+1.5)/0.5)*8=32。这个公式进一步转化为:
    最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目

以上说到的线程池大小的经验值,其实是这种公式的一种估算值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值