线程池----参数详解(一)


本文是讲解线程池的各个参数,以及每个参数的作用及组合使用的方式,关于为什么要使用线程池、怎样使用线程池,本文暂且不论,只是针对于线程池的一些基础参数进行讲解以及各参数之间的联系。

线程池基础参数

线程池的核心类是位于 java.uitl.concurrent 包下的 ThreadPoolExecutor 类,包括平时所说的用工具类Executors 创建线程池,也是基于这个类实现;用编辑器查看它的源码可知,它有四个构造方法, 最终都是指向了下面这个构造方法。

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;
    }

下面就按顺序一一讲解 各个参数的作用

1、corePoolSize

核心线程池大小,线程池中保存的最小存活线程数,默认不会创建线程,创建完线程池之后,线程数为0,之后来了一个任务就会创建一个线程,如果任务超过coreSize,则将任务放到缓存队列中

2、maximumPoolSize

最大线程数,表示线程池中最大线程数,什么时候使用最大线程数里的线程,当poolSize大于核心线程数,并且任务队列里已经满了,则触发最大线程数的线程创建,之后从任务队列中拉取任务,如果任务数大于maxMum,则采用拒绝策略。

3、keepAliveTime

空闲线程存活的时间,当前线程池数量超过corePoolSize 时,当空闲时间达到keepAliveTime 时,多余的空闲线程会被销毁,直到剩下corePoolSize的线程。

4、unit

参数keepAliveTime 的时间单位,有7种,

  • TimeUnit.DAYS; //天
  • TimeUnit.HOURS; //小时
  • TimeUnit.MINUTES; //分钟
  • TimeUnit.SECONDS; //秒
  • TimeUnit.MILLISECONDS; //毫秒
  • TimeUnit.MICROSECONDS; //微妙
  • TimeUnit.NANOSECONDS; //纳秒

5、workQueue

阻塞队列,用来存储等待的任务,也就是被提交,尚未被执行的任务。
1、基于数组的先进先出队列 ArrayBlockingQueue
2、基于链表的先进先出队列,LinkedBlockingQueue,最大为Integer.MAX
3、直接创建一个线程来执行新任务 synchronousQueue

6、threadFactory

表示生成线程池线程的线程工厂,用于标记区分不同线程池所创建出来的线程;

7、handler

线程池执行拒绝策略,当线数量达到maximumPoolSize大小,并且workQueue也已经塞满了任务的情况下,线程池会调用handler拒绝策略来处理请求。

系统默认的拒绝策略有以下几种:

1、AbortPolicy:为线程池默认的拒绝策略,该策略直接抛异常处理。
2、DiscardPolicy:直接抛弃不处理。
3、DiscardOldestPolicy:丢弃队列中最老的任务。
4、CallerRunsPolicy:将任务分配给当前执行execute方法线程来处理。

各参数之间的执行机制

开始学习和使用线程池的时候,没彻底了解过底层源码,我个人这块是有一个误区,就是认为corePoolSize 和 maximumPoolSize 这两个参数配置了,肯定有一定的意义,以及队列满了如何使用拒绝策略,
则任务提交到线程池的策略,可以总结为4点
1、如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;
2、如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;
3、如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;
4、如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。

缓存队列的机制

上面在队列参数那块已经简单介绍过每个队列的机制,下面详细讲解下各个队列的含义:
1、ArrayBlockingQueue:特点是可以保存超过核心线程的任务,并且队列也是有上限的。超过上限,新建线程(满了抛错)。更好地保护资源,防止崩溃,也是最常用的排队策略。
2、LinkedBlockingQueue:无界队列,队列无上限,会导致maimumPoolSize 无用。
3、synchronousQueue:直接提交任务给线程,而不保存它们。

下面的总结的一个简单的示意图
在这里插入图片描述

总结

1、阐述了线程池所使用的的基础类,
2、介绍了每个参数的意义,
3、介绍了每个参数建的相互关系,包括每个池子标识自己的线程工厂,空闲线程的失效时间。
4、详细说了阻塞队列的一些使用策略,当选择无界队列时,maximumPoolSize 就会失去作用

发布了11 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/love_gzd/article/details/105301604