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

目录

一、为什么使用线程池

二、标准库中的线程池

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

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

五、拒绝策略


一、为什么使用线程池

如果有多个线程,一个一个的去创建则需要从就绪状态被调度到运行状态不断切换然后死亡,这样的情况成本比较高。所以频繁的开启或停止线程,线程需要重新被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:先继续执行之前的任务,后续再去执行新提交的任务
相关推荐
愤怒的代码1 分钟前
Spring Boot对访问密钥加解密——HMAC-SHA256
java·spring boot·后端
带多刺的玫瑰1 分钟前
Leecode刷题C语言之切蛋糕的最小总开销①
java·数据结构·算法
API快乐传递者2 分钟前
Python爬虫获取淘宝详情接口详细解析
开发语言·爬虫·python
公众号Codewar原创作者4 分钟前
R数据分析:工具变量回归的做法和解释,实例解析
开发语言·人工智能·python
赵钰老师6 分钟前
基于R语言APSIM模型应用及批量模拟(精细农业、水肥管理、气候变化、粮食安全、土壤碳周转、环境影响、农业可持续性、农业生态等)
开发语言·数据分析·r语言
栗豆包17 分钟前
w118共享汽车管理系统
java·spring boot·后端·spring·tomcat·maven
lly20240623 分钟前
Highcharts 饼图:数据可视化利器
开发语言
夜半被帅醒23 分钟前
MySQL 数据库优化详解【Java数据库调优】
java·数据库·mysql
lw向北.29 分钟前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
万亿少女的梦16829 分钟前
基于Spring Boot的网络购物商城的设计与实现
java·spring boot·后端