线程池原理浅谈

线程池的核心类 ThreadPoolExecutor

我常用的线程池的创建,都是使用基于ThreadPoolExecutor的类去实现的工具类Executors

首先我们来了解一下提供的构造方法

// 第一种构造方法
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
// 第二种构造方法
 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
// 第三种构造方法
  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

 //第四种构造方法
 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

ThreadPoolExecutor这个线程池的核心类中一共给我们提供了四种构造方法,我们从这四个构造方法中找出其核心参数,进行简单的解释。

1、corePoolSize:线程池的核心线程数量

2、maximumPoolSize线程池中允许的最大线数。

3、keepAliveTime :当线程数大于核心线程时,终止多余线程等待新任务的最长时间。

4、 workQueue    :存放任务队列。

5、threadFactory:执行程序创建新线程时使用的工厂。

6、handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。

7、unit- keepAliveTime 参数的时间单位。

线程池的实现原理:

1、用户提交一个任务到线程池

2、判断当前运行的worker数量是否超过corePoolSize,如果不超过corePoolSize,就创建一个工作线程执行该任务。

3、如果worker数量超过corePoolSize,,那么就将该任务加入到workQueue队列中去。 

4、如果workQueue队列数量不超过maximumPoolSize,就创建一个工作线程执行该任务。

5、如果大于maximumPoolSize,就执行性RejectedExecutionHandler拒绝这个任务的提交。

注:线程池最开始是没有worker在运行的 ,maximumPoolSize查看源代码我们会发现,这个值最大是2^29-1=536870911我想至今为止还没有真实的程序开启超过这个最大值的线程数。

如何合理的配置线程池

要想合理的配置线程池,就必须首先分析任务特性,可以从以下几个角度来进行分析:

任务的性质:CPU密集型任务,IO密集型任务和混合型任务。

任务的优先级:高,中和低。

任务的执行时间:长,中和短。

任务的依赖性:是否依赖其他系统资源,如数据库连接。

直白一点 

任务性质不同的任务可以用不同规模的线程池分开处理。

CPU密集型任务配置尽可能少的线程数量,如配置Ncpu+1个线程的线程池。

IO密集型任务则由于需要等待IO操作,线程并不是一直在执行任务,则配置尽可能多的线程,如2*Ncpu。

混合型的任务,如果可以拆分,则将其拆分成一个CPU密集型任务和一个IO密集型任务,只要这两个任务执行的时间相差不是太大,那么分解后执行的吞吐率要高于串行执行的吞吐率,如果这两个任务执行时间相差太大,则没必要进行分解。我们可以通过Runtime.getRuntime().availableProcessors()方法获得当前设备的CPU个数。

 (N为CPU总核数)

  • 如果是CPU密集型应用,则线程池大小设置为N+1
  • 如果是IO密集型应用,则线程池大小设置为2N+1

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值