本篇会加入个人的所谓鱼式疯言

❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言

而是理解过并总结出来通俗易懂的大白话,

小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.

🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!

在这里插入图片描述

在当今这个多核处理器成为标配的时代,如何高效地利用计算资源已成为软件开发中不可忽视的关键因素。随着应用程序变得越来越复杂,对并发处理的需求也日益增长。试想一下,在一个繁忙的服务器上,如果每一个新任务都创建一个新的线程来处理,那么系统将不堪重负——频繁的线程创建和销毁不仅消耗大量的时间和内存,还可能导致系统性能急剧下降。

前言

为了解决这一问题,并实现 更高效的资源管理 ,线程池 的概念应运而生。线程池是一种用于 管理和复用一组预先创建好的线程 的方法,它通过预先创建一定数量的工作线程并将其 置于池中等待分配任务 ,从而 避免了频繁创建和销毁线程 带来的开销。

接下来的内容中,小编将带着小伙伴深入探讨 线程池的基本原理 、 参数类型

目录

  1. 线程池的初识

  2. Java标准库中线程池的参数列表(重点)

一. 线程池的初识

1. 线程池的引入

我们知道,线程对于进程来说, 线程是 更微量的进程 ,开销更小, 但对于线程的本身来说虽然开销比较大。

但随着当前 并发编程的日益需求 越来越大, 频繁的从系统中 创建线程 , 销毁线程的开销 还是相对而已比较大的。

所以我们就引入 “线程池” 的概念, 具体线程池是什么,该怎么理解,下面让小编具体来说明下吧

2. 线程池的概念以及理解

<1>. 线程池的概念

池 的概念好比一个地方,这个地方操作系统提前创建 好多线程 放在这个地方。

当 任务繁忙 的时候,我们就 从这个地方中调用这些线程 。

当 任务不繁忙 的时候,我们就把这些 线程重新调度回这个地方 。

而这个地方我们就成为 “线程池” 。

<2>. 线程池的理解

我们知道, 线程是操作系统进行 调度执行的基本单位 。

每次创建线程是从操作系统中 创建并且调度执行的 。

操作系统可以简单 分为 内核区 和 用户区。

内核区 是操作系统硬件的内层管理

用户区 是各种软件资源的任务执行

而操作系统面对多个软件的运行事务是十分繁忙的, 每创建一个 线程 去调度执行任务也不可控的。

好比现在小编要去银行去办理取钱事务, 就想柜台提出诉求, 但柜台说需要户口本复印件。

这时银行这边刚好有打印机

我有两种方式可以得到户口本的复印件

  1. 请柜台小姐姐帮我打印一下

  2. 自己动手打印

如果我们操作系统创建线程的, 就相当于请柜台小姐姐帮我 打印户口本 ,但柜台小姐姐的事务是 比较繁忙的 , 这个执行是 不可控的 , 我们并不知道柜台小姐姐什么时候完成事务来帮我打印户口本。

所以就像我们的操作系统创建线程一样,由于我们的操作系统是繁忙的,就有可能对于创建线程的这种需求,造成 一定的开销。

而我们在线程池中去调度执行线程, 就好比上面的第二种方案,这是我们自己的去动手完成我们自己的需求,具体需要多久去完成,这些操作是由我们自己决定的, 这种行为是可控的。 所以 开销势必会少很多 , 也会 更轻量 。

二. Java标准库中线程池的参数列表(重点)

在我们 Java标准库 中提供一个很多类来创建我们的 线程池 来进行 任务的执行。

其中我们重点讲解面试中常考的这个类,ThreadPoolExecutor (很多参数) ,

因为这个 参数比较多 , 也很麻烦,下面让小编仔细到来。

1. ThreadPoolExecutor

ThreadPoolExecutor 这个类来自于 java.util.concurrent 这个包。

在这里插入图片描述

在这个方法中, 我们有提供七个参数, 是 面试场合中HR比较喜欢问的话题 。

下面就让小编来 细细道来 吧。

2. corePoolSize 和 maximumPoolSize

corePoolSize: 线程核心数, 就是说在这个线程中都必须有的元老级别的线程, 在创建这个线程池是就至少有这些线程。

在我们的线程池中,有两类线程: 核心线程和非核心线程

当我们 任务繁忙 时, 核心线程和非核心线程都会 被创建出来一起工作 。

当我们 任务不繁忙 时, 只需要核心线程来工作, 而非核心线程就会被销毁 。

所以一定会 执行的是核心线程,任务繁忙被销毁的 , 就是我们的非核心线程。

maximumPoolSize : 最大线程数

而我们的 最大线程数= 核心线程数 + 非核心线程数。

而真正限制 最大线程数 的主要因素就是我们的 CPU的核心数。

鱼式疯言

核心线程: 好比我们一个公司的正式员工,无论公司是否繁忙, 公司都是需要的, 不会随意开除正式员工。

非核心线程: 好比我们一个公司的实习生, 只有当公司繁忙时,实习生才会 被录用 , 而 当公司不繁忙时 , 实习生就会 被开除 。

3. keepAliveTime 和 unit

一个线程是 有可能没有任务去工作 ,这时操作系统就需要考虑要不要 回收释放这个线程资源, 就需要考虑这个线程需要 空闲的最大时间,

keepAliveTime : 允许空闲的最大时间, 一旦 实际的空闲时间 超过这个 允许空闲的最大时间 ,这个线程就会 被释放 。

unit: 允许空闲的最大时间的单位设置, 这里的单位设置就有很多种: 毫秒,妙, 日,月,年等…

鱼式疯言

允许空闲的最大时间 : 就好比一个实习生需要去不断的去工作,如果这个实习生没有任务可做,空闲下来了 ,一旦超过这个允许空闲的最大时间,公司就会把这个实习生给开除掉。

4. workQueue

在我们线程中,不同的线程可能执行不同的任务, 而这些任务该怎么存放和管理呢?

于是我们就借助了一个特殊的队列: 阻塞队列

workQueue:工作队列:对于这个队列本质上是一个Running类型的阻塞队列用于我们工作队列: BlockingQueue<running> workQueue = new BlockingQueue<running>; , 这个队列我们就需要把需要完成的任务都存放在这个 工作队列 中, 进行工作。

鱼时疯言

此处的队列:

  1. 队列的大小: 程序员自己定义Size

  2. 队列的类型: 程序员自己决定

5. threadFactory

对于我们线程池的初始化, 我们可能会想到构造方法, 但是 构造方法也可能会出现问题 , 于是我们就引入一种设计模式(套路) : 工厂设计模式 来进行补充 我们构造方法对于线程池初始化的不足 。

构造方法的问题:

因为构造方法会对于 类型不同,数量不同 的方法会发生 重载 。

而对于 类型相同,数量相同的构造方法 来说,就不会发生 重载 ,就无法实现我们 多个参数的初始化 。

线程工厂: 在我们线程工厂中设计了一种普通的 成员方法(静态方法) 来通过执行我们的方法对线程池中的 成员变量 进行 初始化操作 , 从而解决构造方法重载的不足问题。

鱼式疯言

有图有真相

在这里插入图片描述

6. handler (重点掌握)

对于线程过多, 执行的任务超出了我们的 最大限度 , 线程池 会通过 阻塞等待的操作 来 防止任务过满 吗?

答案是 不会的 .

hander: 拒绝策略:对于任务过满,任务加载过多的情况, 我们的会根据不同的情况采用 4 种不同的策略 来安排我们下一步该怎么操作。

4种不同的策略:

在这里插入图片描述

<1>. AbortPolicy

这种处理方式就比较简单粗暴,当 任务过满 时, 添加任务时就会 直接抛出异常, 相当于这个无论是当前讲要执行的任务,还是之前的任务都无法执行,程序直接中断。

<2>. CallerRunspolicy

这种处理方式就比较友好,当任务过满时, 线程池会 拒绝执行新增加的任务 ,而是按照常规任务 继续执行 。

<3>. DifcardOldestPolicy

当任务过满时,这个方式就是把最老的那个任务给踢掉,让 新的任务添加进来执行。 这样保证任务 不会出现过满 的情况,也能执行到 新的任务 。

<4>. DiscardPolicy

当任务过满时, 这个方法就是在 任务队列 中, 把 最新的那个任务给踢掉

注意: 在任务队列中踢掉的任务,是 其他线程也不能执行到的 。

鱼式疯言

给小伙伴举个生活中的栗子吧 😁 😁 😁 😁

有一天小爱同学和我同时写博客, 她突然跑过来说,让我过去帮她写一下,有些东西不是很懂, 但我现在也要写博客啊,那就会采取下面4 种策略。

  1. 抛出异常: 我直接告诉小爱同学,今天好累啊,我都有点不想写博客了, 于是小爱同学的博客没有帮忙写,小编自己的博客同时也没写,新的任务和之前的任务都不执行 , 直接摆烂了。

  2. 拒绝执行: 我告诉小爱同学,你先自己搞搞呗,我这边自己还得写博客呢 ,这样新的任务我 拒绝执行 了, 我还是 继续执行我自己的任务 , 她去执行她自己的任务。

  3. 踢掉老任务: 小爱同学找我帮忙,于是我就把任务中最老的任务给踢掉,直接去执行她的那个新任务了。

  4. 踢掉新任务: 小爱同学找我帮忙,我就和小爱同学说,你先别写,先看我平常是怎么写的,于是我就把这个新任务都踢掉,大家不去执行这个新的任务 。

总结

  • 线程池的初识: 线程池对于线程开销的认识以及背后更好去调度的原理理解。
  • . Java标准库中线程池的参数列表(重点): 认识到对于 ThreadPoolExecutor 这个类的认识是来源于 java.util.concurrent这个包, 并且熟悉了七个参数的用法,理解了工厂设计模式,和拒绝策略的4种不同方式。

如果觉得小编写的还不错的咱可支持 三连 下 (定有回访哦) , 不妥当的咱请评论区 指正

希望我的文章能给各位宝子们带来哪怕一点点的收获就是 小编创作 的最大 动力 💖 💖 💖

在这里插入图片描述

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐