线程池核心参数介绍

目录

线程池核心参数说明       

JDK自带的4种线程池创建

手工创建线程池及线程池参数设置建议


线程池核心参数说明       

        使用线程池可以对线程统一管理,合理分配CPU和内存。使用线程池的主要场景有:批量任务计算、多文件处理、大文件解析(Excel等)。线程池ThreadPoolExecutor包含7个核心参数,构造方法如下:

public ThreadPoolExecutor(
       int corePoolSize,
       int maximumPoolSize,
       long keepAliveTime,
       TimeUnit unit,
       BlockingQueue<Runnable> workQueue,
       ThreadFactory threadFactory,
       RejectedExecutionHandler handler) {}
  • corePoolSize 核心线程数
  • maximumPoolSize 最大线程数,在核心线程数的基础上,额外增加线程数
  • keepAliveTime 线程空闲时间,如果线程池当前的线程数多于corePoolSize,多余的线程空闲时间超过keepAliveTime,它们就会被终止
  • unit 时间单位
  • workQueue 阻塞任务队列

常用的阻塞任务队列(队列为空时,获取队列要素时阻塞等待,队列满时,插入队列要素时阻塞等待)有:
LinkedBlockingQueue:无界队列,队列任务可以多到Integer.MAX_VALUE
SynchronousQueue:同步队列,即任务到来时,不放入队列等待,直接交给工作线程执行任务
DelayedWorkQueue:延迟队列
ArrayBlockingQueue:有界队列,队列容量大小确定
PriorityBlockingQueue:优先级有界队列,队列容量大小确定

  • threadFactory 线程工厂,当线程池需要新的线程时,通过它生成新的线程
  • handler 拒绝策略,默认是AbortPolicy,会抛出异常。

线程池中线程创建规则:

  1. 若线程总数小于corePoolSize时,新任务到来时(即使有线程处于空闲状态)会创建一个新线程。
  2. 若线程数等于corePoolSize,再来任务时,会把任务放入workQueue队列去等待。
  3. 若workQueue队列满了,如果此时线程数小于maximumPoolSize,则会再创建新线程来执行任务。
  4. 若workQueue队列已满,并且线程数已经扩大到等于maximumPoolSize时,再尝试添加任务时,则执行拒绝策略

JDK自带的4种线程池创建

1、单个线程线程池SingleThreadExecutor

核心线程数和最大线程数都是1,任务队列采用无界队列LinkedBlockingQueue

2、固定大小线程池FixedThreadPool

核心线程数和最大线程数都是n(参数),任务队列采用无界队列LinkedBlockingQueue

注意:当任务量很多,每个任务执行时长很长,导致大量的任务放入无界队列LinkedBlockingQueue,此种情况会发生OOM问题

3、缓存线程池CachedThreadPool

核心线程数0,最大线程数Integer.MAX_VALUE,任务队列采用同步队列SynchronousQueue

注意:当任务量很多,此线程池会创建大量的线程,此时可能会发生OOM问题

4、定时调度线程池ScheduledThreadPoolExecutor

 核心线程数(参数传递),最大线程数Integer.MAX_VALUE,任务队列采用延迟队列DelayedWorkQueue

手工创建线程池及线程池参数设置建议

        了解了线程池的核心参数后,建议手工创建线程池,不使用JDK自带的线程池,示例如下:

package com.gingko.threadpool;
import java.util.concurrent.*;
public class MyThreadPool {

    /**
     * 手工创建线程池
     * @param corePoolSize 核心线程数
     * @param maximumPoolSize 最大线程数
     * @param keepAliveTime 空闲时间
     * @param taskNum 任务队列容量
     * @return
     */
    public static ExecutorService newThreadPool(int corePoolSize,int maximumPoolSize,
                                                int keepAliveTime,int taskNum) {
        return new ThreadPoolExecutor
                (corePoolSize, maximumPoolSize,
                        keepAliveTime, TimeUnit.SECONDS,
                        new LinkedBlockingQueue(taskNum),
                        Executors.defaultThreadFactory(),
                        new ThreadPoolExecutor.AbortPolicy());
    }

    public static void main(String[] args) {
        /**
         * 手工创建了一个线程池,核心线程数10,最大线程数20,任务队列100,使用默认的线程工厂生成线程,拒绝策略选择AbortPolicy
         */
        newThreadPool(10,20,60,100);
    }
}

说明:手工创建了一个线程池,核心线程数10,最大线程数20,任务队列100,使用默认的线程工厂生成线程,拒绝策略选择AbortPolicy

线程池参数设置建议:

  • CPU密集型任务(大量计算):最佳线程数为CPU核心数的1-2倍左右。
  • IO耗时型任务(读写数据库、文件、网络读写等):最佳线程数一般会大于CPU核心数很多倍。参考Brain Goetz推荐的计算方法,线程数=CPU核心数*( 1+平均等待时间/平均工作时间 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值