关于线程池,陆陆续续有一些了解,但是都是看的题,对应底层的对象不怎么了解,这周想起来去看了看相关的东西。
线程池使用的条件:我们之前说的是:其实就是管理线程的容器。它可以管理线程,防止线程过多(避免无节制创建线程),导致系统崩溃。并且它可以让线程复用。本质就是将线程创建和销毁本身带来的开销分摊到具体任务上,任务执行次数越多,则节省时间越多,并且线程池将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关。
所以为什么使用线程池?因为系统资源有限,创建线程非常消耗系统资源,为了保证系统的正常运行,所以我们需要减少线程创建,以提高我们系统的性能。
在之前我们了解过常量池,常量池其实就是对字符串进行管理的一个东西,当String s=“hdjhsk”
时候,先求常量池寻找hdjhsk,如果没有就创建,如果有就直接复用。线程池看起来在复用情况上和他类似。
当任务需要创建某线程时候,先去线程池里面寻找,如果有就直接复用,如果没有就涉及重新创建,但是这个创建有好几种条件。我们知道线程池有几个关键参数,比如:最大线程数,核心线程数,等待队列,拒绝策略,空闲线程存活时间。
那么在创建线程时候,我们首先判断有没有到核心线程,如果道理就进行等待队列的查看,如果等待队列也满了,就开始查看是否到达最大线程,如果到了,就不能创建该线程,需要拒绝执行该条语句。美国线程有一个空闲存活时间,如果时间到了,该线程就会消亡。
关于核心线程,等待队列,最大线程数三者判断,很多文章倾向的是先判断核心线程,再判断等待队列,然后判断最大线程数。这是为什么捏?首先核心线程数第一个判断大家都知道,可以立即,为什么中间是等待队列捏,因为我们怎么判断一个线程池满?就是查看他是否到达了最大线程数。
临时线程数 = 最大线程数 - 核心线程数
- private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); 用于定义一个原子整型变量 ctl,用于控制线程池的状态和线程数量。默认状态为 RUNNING,线程数量为 0。
- private static final int COUNT_BITS = Integer.SIZE - 3; 定义一个常量 COUNT_BITS,用于方便后面对 ctl 进行位运算。根据 Java 中 int 类型的大小,一个 int 类型可以存储 32 位二进制数,而高 3 位用于存储线程池的状态,因此实际可用的位数为 29(2^29 = 536870912)。
- private static final int CAPACITY = (1 << COUNT_BITS) - 1; //线程池中线程的最大数量2^29-1 定义一个常量 CAPACITY,用于表示线程池中线程的最大数量,即 2^29-1。
- private static int runStateOf(int c) { return c & ~CAPACITY; } //获得线程池中工作线程的数量 private static int workerCountOf(int c) { return c & CAPACITY; } 定义两个静态方法,分别用于获得线程池的状态和线程数量。将 ctl 分解为高 3 位和低 29 位,通过位运算得到线程池的状态和线程数量。
- private static int ctlOf(int rs, int wc) { return rs | wc; } 定义一个静态方法,用于将线程池的状态和线程数量合并成一个 ctl 变量。将状态的二进制数和数量的二进制数进行按位或运算得到 ctl。