【多线程】线程池的简单实现与线程池的拒绝策略

目录

一、为什么使用线程池

二、标准库中的线程池

三、线程池的简单代码实现

四、标准库中线程池的构造方法解读

五、拒绝策略


一、为什么使用线程池

如果有多个线程,一个一个的去创建则需要从就绪状态被调度到运行状态不断切换然后死亡,这样的情况成本比较高。所以频繁的开启或停止线程,线程需要重新被CPU调度到运行状态,需要发生CPU的上下文切换,效率比较低。而线程池是复用机制,它会提前创建好一些固定的进入运行状态的线程,从而减少就绪状态到运行状态的切换

二、标准库中的线程池

java 复制代码
    public static void main(String[] args) throws InterruptedException {
    		// 1. 创建线程池
		ExecutorService pool = Executors.newCachedThreadPool();
		// 2. 提交任务
		pool.submit(new Runnable() {
			@Override
			public void run() {
				System.out.println("线程1");	
			}
		});
	}

三、线程池的简单代码实现

一个线程池可以同时提交n个任务,在线程池中会有m个线程去执行这n个任务,我们可以基于生产者消费者模型来实现线程池,首先我们需要一个阻塞队列来存储提交的任务,然后在构造方法中创建出m个线程去执行这些任务

java 复制代码
class Pool {
	// 1. 创建阻塞队列
	private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(10);

	// 2. 提交任务
	public void submit(Runnable task) throws InterruptedException {
		queue.put(task);
	}

	// 3. 构造方法中创建出线程
	public Pool (int m) {
		for (int i = 0; i < m; i++) {
			Thread t = new Thread() {
				@Override
				public void run() {
					while (true) {
						try {
							queue.take().run();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			};
			t.start();
		}
	}
}

四、标准库中线程池的构造方法解读

我们先来看一下线程池的核心构造方法

java 复制代码
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
}

其中第一次个参数corePoolSize表示线程池里核心线程数的个数,第二个参数表示线程池中最大线程数,既然有了核心线程数那么为什么会有最大线程数呢?举个例子,一个公司在任务不多的情况下可能只需要核心的员工就够了,但是忽然有一天任务忽然增多原有的核心员工不够了这个时候就会招聘对应数量的实习生来执行这些任务,最大线程数就是核心线程数加上临时的线程数,那接下来的两个参数也是针对这些"实习生"的,他表示当任务不紧急的多久时间后销毁这些线程,第五个参数也就是workQueue,在上面线程池的实现中我们了解了在线程池中有一个专门存储任务的任务队列,这个参数也是一个任务队列,在创建线程池的时候你可以选择传入一个自己的任务队列,也可以选择不传入,就好比大一新生开学你可以选择学校提供的被褥也可以选择自带被褥,关于最后一个参数handler,他是用于选择线程池使用哪一个拒绝策略的,会在下面提到

五、拒绝策略

什么是线程池的拒绝策略呢?当线程池中的任务队列已经满了时,再有新的任务提交进来时线程池会根据不同的拒绝策略采取不同的措施》》》

  • ThreadPoolExcutor.AbortPolicy:直接抛出异常,之前的任务也会停止
  • ThreadPoolExcutor.CallerRunsPolicy:将任务交给调用者去执行,如果调用者执行不了,该任务会被丢弃
  • ThreadPoolExcutor.DiscardoldestPolicy:将最老的任务丢弃来执行新的任务,执行完成后再去执行老的任务
  • ThreadPoolExcutor.DiscarPolicy:先继续执行之前的任务,后续再去执行新提交的任务
相关推荐
for_ever_love__9 分钟前
LangChain Token 计数与成本控制:先知道钱花在哪
开发语言·langchain
m0_547486669 分钟前
《数据结构 (C语言)》期末试卷及答案(10套)2026版
c语言·开发语言·数据结构
顽疲11 分钟前
Java vue 养老系统源码详解:入住核算单 live-check 缴费入账与预交金收据实践
java·vue.js·python·java 养老·springboot 养老·vue养老
Sand(ContextGate)13 分钟前
从开发者调试工具到消费级 App:一个 AI 电商导购项目的 C 端改造与 6 个连环踩坑实录
开发语言·人工智能·python·ai·langchain
共饮一杯无17 分钟前
LiveKit本地录制落盘路径排查与修复实践
java·go·livekit
白杨尚青18 分钟前
C++入门篇(十七):priority_queue 完整模拟实现——仿函数、区间建堆与指针特化(附完整代码仓库)
开发语言·c++·stl·仿函数
StevenLdh28 分钟前
第八期 · 情绪闯关挑战盒:一个「无惩罚」成就系统的数据建模
java·微信小程序
逐光者93331 分钟前
滤波器的 R 与 C 如何选择:从截止频率到工程实践
c语言·开发语言·r语言
Eider199836 分钟前
大模型输出格式幻觉解决思路
开发语言·前端·javascript
Wang's Blog37 分钟前
Java 项目实战: 交友项目 - 入门案例:编写 Dubbo 服务消费者
java·dubbo·交友