线程池
- 🍉简介
- 🍉标准库中的线程池
- 🍌线程池的执行流程
- 🍉Executors
- 🍉实现一个简单的线程池
🍉简介
“池”是一个非常重要的概念,我们之前学的字符串常量池就是一种常量池

- 提前把要用的对象准备好
- 对象用完后也不要立即释放,而是先留着,以备下次使用
我们主要来分析 它是存放线程的池,会把要使用的线程,用完之后也不会立即释放,而是。这样就可以节省创建及销毁线程的开销
🍉标准库中的线程池
标准库提供了 这个类,它的构造方法有很多参数

我们分别来解释一下每个参数的含义
- corePoolSize —— 核心线程数
标准库提供的线程池,它所持有的线程数并非是一成不变的,而是会根据当前任务量,自适应调节线程个数。即如果任务非常多,那就会多搞几个线程;反之则会缩减线程数
核心线程数就是一个线程池里最少有多少个线程 - maximumPoolSize —— 最大线程数
顾名思义,就是最多能有多少个线程 - keepAliveTime —— 保持存活时间
就是某个线程,它的如果超过这个时间阈值,那就会被销毁掉(或者说空闲状态下能存活多久) - unit —— 保持存活时间的时间单位(h、min、s、ms……)
- workQueue —— 一个阻塞队列
和定时器类似,线程池中也可以持有多个任务,所以用一个阻塞队列来存放任务,如果任务有优先级的话,可以用 PriorityBlockingQueue。Runnable 是用来描述任务的主体java并发基础教学 - threadFactory —— 线程工厂
首先要解释一下什么是工厂模式
工厂模式是一种常见的,通过专门的来创建指定的对象
它本质上是给 Java 语法填坑的。这里的“坑”指的是,方法重载没办法在返回值相同的前提下,重载参数个数相同、类型一样的方法
而有时候要重载的方法,它们参数列表中的参数个数和类型虽然一样,但是意思不一样
举个例子,现在有一个类 Point,要用它来表示平面直角坐标系中的点,在数学中有两种表达形式:常规的坐标和极坐标
这样写编译器会报错
我们可以把原先两个方法改成静态方法,直接在方法内部创建一个对象并初始化,然后再返回这个对象
这种把创建对象和初始化封装起来,在静态方法内部完成这些操作的过程,想得到对象,就调用这个方法,它就会“加工”出一个对象,这就是工厂模式。代码如下:

讯享网
- handler —— 拒绝策略
这个参数是最重要的一个参数
线程池中的阻塞队列能够容纳的元素是有上限的,如果往队列中添加任务时,任务队列已经满了,那线程池会怎么做呢?
这就涉及到拒绝策略了
有四种策略
①:直接抛出异常。此时原先任务和新任务都不执行
②:新的任务由添加任务的线程去执行,就是“谁揽的活谁去干”。此时新任务就不由线程池执行了
③:丢弃最老的任务
④:丢弃最新的任务
🍌线程池的执行流程
- 当一个新任务交给线程池,如果此时线程池中有空闲的线程,就会直接执行
- 如果没有空闲的线程且当前线程池的线程数量小于corePoolSize,就会创建新的线程来执行任务,否则就会将该任务加入到阻塞队列中
- 如果阻塞队列满了,就会创建一个新线程,从阻塞队列头部取出一个任务来执行,并将新任务加入到阻塞队列末尾
- 如果当前线程池中线程的数量等于maximumPoolSize,就不会创建新线程,就会去执行拒绝策略
🍉Executors
由于 ThreadPoolExecutor 参数比较多,用起来比较复杂,所以标准库还提供了另一个版本 —— ,它是由 ThreadPoolExecutor 后得到的,通过 Executors 创建出来的线程池对象,它内部已经把 ThreadPoolExecutor 创建好了并设置了参数

Q:Executors 和 ThreadPoolExecutor 分别在什么时候使用?
A:如果没什么要求,只是简单使用一下,那就用 Executors;而如果想要高度定制化(diy),那就使用 ThreadPoolExecutor,参数都由自己设置,掌控权在我们手上,这样可以避免一些不可控因素
🍉实现一个简单的线程池
方便起见,我们写一个线程数目固定的线程池
构造方法指定创建多少个线程,并把这些线程创建好。然后要有一个阻塞队列,持有要执行的任务。还要提供一个方法 —— submit,它用来添加新任务
测试一下:
讯享网
结果如下:

因为线程是随机调度的,所以任务序号是无序的
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/8430.html