线程池原理解析

article/2025/10/7 8:07:33

1、为什么要用线程池,线程池的作用(意义),如果使用线程池会有什么好处,说说你对线程池的了解?

 

创建和销毁线程的代价是很大的,线程不像创建普通object对象那样,在堆中分配点内存就好了的,在new Thread的时候,是先分配内存,但是并没有创建线程,当调用线程的start方法的时候,会通过cpu指令创建一个线程。所以,频繁的创建线程、销毁线程的代价是很大的,会导致系统性能下降。还有,如果频繁创建线程,不加以管理,会导致系统线程过多,影响系统运行。

如果用线程池,指定线程数量,线程池会帮助我们管理线程,我们使用线程可以从线程池获取一个线程,线程干完活,在放回池子里,不会销毁。而且有线程池管理线程,能有效控制线程的数量,不会导致系统创建过多的线程。

  • 创建和销毁线程的代价是很大
  • 能有效控制线程的数量,不会导致系统创建过多的线程。

 

 

 

2、线程池的内部结构(组成)?

Java线程池包含4个部分,线程池的工作原理,是生产者消费者模式的

 

(1)线程池管理器(ThreadPool):就是负责创建和销毁线程池的

(2)工作线程(PoolWorker):就是线程池中的一个线程

(3)工作任务(Task):这个就是线程池里的某个线程需要执行的业务代码,这个是你自己编写的业务逻辑

(4)任务队列(TaskQueue):这个是扔到线程池里的任务需要进行排队,要进任务队列

 

 

 

3、常用的线程池有哪些?

(1)SingleThreadExecutor(单线程线程池,很少用 -> 自己做一个内存队列 -> 启动后台线程去消费)

里面就一个线程,慢慢消费

 

(2)FixedThreadExecutor(固定数量线程池):比如说,线程池里面固定就100个线程,超过这个线程数就到队列里面去排队等待

 

(3)CachedThreadExecutor(自动回收空闲线程,根据需要自动新增线程,传说中的无界线程池???真的无限界吗?):无论有多少任务,根据你的需要,无限制的创建任意多的线程,在最短的时间内来满足你,但是高峰过去之后,如果有大量的线程处于空闲状态,没有活儿可以干,等待60s之后空闲的线程就被销毁了

 

(4)ScheduledThreadExecutor(线程数量无限制,支持定时调度执行某个线程):提交一个任务,对于这个任务不是立马执行的,是可以设定一个定时调度的逻辑,比如说每隔60s执行一次,这个一般不用,一般来说就用spring schedule的支持

 

一般其实最常用的是 FixedThreadExecutor 和 CachedThreadExecutor

 

4、线程池有哪些常用的API?

 

(1)Executor:代表线程池的接口,有个execute()方法,扔进去一个Runnable类型对象,就可以分配一个线程给你执行

 

(2)ExecutorService:这是Executor的子接口,相当于是一个线程池的接口,有销毁线程池等方法

-> ExecutorService就代表了一个线程池管理器,会负责管理线程池 ->负责 线程的创建和销毁 -> 队列排队

 

(3)Executors:线程池的辅助工具类,辅助入口类,可以通过Executors来快捷的创建你需要的线程池。

创建线程池的入口类,包含newSingleThreadExecutor()、newCachedThreadPool()、newScheduleThreadPool()、newFixedThreadPool(),这些方法,就是可以让你创建不同的线程池出来

 

(4)ThreadPoolExecutor:这是ExecutorService的实现类,这才是正儿八经代表一个线程池的类,一般在Executors里创建线程池的时候,内部都是直接创建一个ThreadPoolExecutor的实例对象返回的,然后同时给设置了各种默认参数。

 

如果我们要创建一个线程池,两种方式,要么就是Executors.newXX()方法,快捷的创建一个线程池出来,线程池的所有参数设置都采取默认的方式;要么是自己手动构建一个ThreadPoolExecutor的一个对象,所有的线程池的参数,都可以自己手动来调整和设置

 

5、用executor怎么创建线程池,怎么用的?

 

源码:

 

 

Executors使用:

 

 

6、说一下线程池配置的几个参数?

3.3 线程池的构造参数和真正的工作原理

 

 

ThreadPoolExecutor就是线程池,那么这个类的构造函数的所有入参,就是你可以设置的参数,我们来解释一下这些参数吧

 

  • corePoolSize:线程池里的核心线程数量

 

  • maximumPoolSize:线程池里允许有的最大线程数量

 

  • keepAliveTime:如果线程数量大于corePoolSize的时候,多出来的线程会等待指定的时间之后就被释放掉,这个就是用来设置空闲线程等待时间的

 

  • unit:这个是上面那个keepAliveTime的单位

 

  • workQueue:这个是说,通过ThreadPoolExecutor.execute()方法扔进来的Runnable工作任务,如果所有线程都繁忙,会进入一个队列里面去排队,这就是那个队列

 

  • threadFactory:如果需要创建新的线程放入线程池的时候,就是通过这个线程工厂来创建的

 

  • handler:假如说上面那个workQueue是有固定大小的,如果往队列里扔的任务数量超过了队列大小,咋办?就用这个handler来处理,
    • AbortPolicy、
    • DiscardPolicy、
    • DiscardOldestPolicy,
    • 默认:如果说线程都繁忙,队列还满了,此时就会报错,RejectException

 

7、结合线程池的参数,说说线程池的工作原理?线程池启动线程的原理(说说线程池的底层原理)?

上来就画图

然后假设参数是这些

注意:队列大小可以自己设置,如果不设置,那大小就是(核心线程数+最大线程数)

 

总结一下下面这些话:总的来说,就是先创建线程到核心线程数,然后再把队列塞满(放四个还是放2个(队列+核心线程数)??https://blog.csdn.net/shixing_11/article/details/7109471),如果队列满了,再来任务,就再创建线程(最多可以创建,最大线程数 - 核心线程数),这时候创建的几个线程如果长时间不工作是要回收的。如果线程总数达到了最大线程数,而且,队列满了,那就走handler的策略,默认抛出rejectExectorException

 

(1)一开始线程池里的线程是空的,一个都没有。

有一个变量维护的是当前线程数量,这个变量是poolSize,poolSize = 0,

如果当前线程的数量小于corePoolSize(2),poolSize < corePoolSize,

那么来了一个任务优先创建线程,直到线程池里的线程数量跟corePoolSize一样;

poolSize = 1,poolSize < corePoolSize(2),又创建一个线程来处理这个任务;poolSize = 2

 

(2)如果当前线程池的线程数量(poolSize = 2)大于等于corePoolSize(2)的时候,而且任务队列没满(最大大小是4,但是当前元素数量是0),那么就扔到任务队列里去

 

 

(3)如果当前线程池的线程数量大于等于corePoolSize的时候,而且任务队列满了(不一定是4,可以自己设置)(最大大小是4,当前已经放了4个元素了,已经满了),那么如果当前线程数量小于最大线程数(poolSize = 2,maimumPoolSize = 4,poolSize < maximumPoolSize),就继续创建线程;poolSize = 3,提交了一个任务,poolSize >= corePoolSize,任务队列满,poolSize < maximumPoolSize,再次创建一个任务

 

 

(4)如果此时poolSize >= corePoolSize,任务队列满,poolSize == maximumPoolSize,此时再次提交一个任务,当前线程数已经达到了最大线程数了,那么就使用handler来处理,默认是抛出异常,ThreadPoolRejectExeception

 

 

(5)此时线程池里有4个线程,都处于空闲状态,corePoolSize指定的是就2个线程就可以了,但是此时超过了corePoolSize 2个线程,所以如果那超出的2个线程空闲时间超过了60s,然后线程池就会将超出的2个线程给回收掉

 

如何设置池的这些参数?先来看看创建线程池的默认代码

 

其实上面都说过了,啥时候会创建新线程?其实就是线程数没到corePoolSize的时候,会创建线程;接着就是任务队列满了,但是线程数小于maximumPoolSize的时候,也会创建线程;创建的时候通过threadFactory来创建即可

 

7、线程池队列满的时候怎么处理(FixedThreadPool满了之后会怎么办)?

如上个问题,如果队列满了,就会创建新的线程,如果最大线程数比核心线程数大的话,然后等线程池中的线程数量达到最大数量了,并且队列也满了,那就抛异常(也可以选择别的策略)RejectExectingException

 

8、FixedThreadPool 的工作原理?

源码:

(1)核心线程数,等于最大线程数

(2)超时时间(根本不会超时,因为都是核心线程,所以就写个0L)

(3)创建了一个 LinkedBlockingQueue 无界队列 ,只要有任务就会往队列里加,知道内存溢出

 

 

9、CachedThreadPool的工作原理

源码:

(1)corePoolSize = 0,maximumPoolSize = 最大值(无限大),keepAliveTime = 60s,workQueue=SynchronousQueue

(2)SynchronousQueue(实际上没有存储数据的空闲,是用来做多线程通信之间的协调作用的),一开始提交一个任务过来,要求线程池里必须有一个线程对应可以处理这个任务,但是此时一个线程都没有,poolSize >= corePoolSize , workQueue已经满了,poolSize < maximumPoolSize(最大值),直接就会创建一个新的线程来处理这个任务

(3)如果短期内有大量的任务都涌进来,实际上是走一个直接提交的思路,对每个任务,如果没法找到一个空闲的线程来处理它,那么就会立即创建一个新的线程出来,来处理这个新提交的任务

(4)短时间内,如果大量的任务涌入,可能会导致瞬间创建出来几百个线程,几千个线程,是不固定的

(5)但是当这些线程工作完一段时间之后,就会处于空闲状态,就会看超过60s的空闲,就会直接将空闲的线程给释放掉

 

10、FixedThreadPool 和 CachcedThreadPool 的区别

  把上面那个说一下,然后加上下面这些

(1)FixedThreadPool:线程数量是固定的,如果所有线程都繁忙,后续任务全部在一个无界队列里面排队,无限任务来排队,直到内存溢出

(2)CachcedThreadPool:线程数量是不固定的,如果一下子涌入大量任务,没有空闲线程,那么就创建新的线程来处理;如果有空闲线程,就是一个任务配对一个空闲线程来处理;如果线程空闲时间超过60s,就给回收掉空闲线程,线程大小无限大有点不靠谱,容易挂。4核8G的虚拟机,100个线程就差不多了,cpu可能就快达到了70%,80%

 

 

11、不同线程池的使用场景是什么?

FixedThreadPool:比较适用于什么场景呢?负载比较重,而且负载比较稳定的这么一个场景,我给大家来举个例子,我们之前线上有一套系统,负载比较重,后台系统,每分钟要执行几百个复杂的大SQL,就是用FixedThreadPool是最合适的。

 

因为负载稳定,所以一般来说,不会出现说突然瞬间涌入大量的请求,100个线程处理不过来,然后就直接无限制的排队,然后oom内存溢出,死了

 

CachedThreadPool:负载很稳定的场景,用CachedThreadPool就浪费了;每天大部分时候可能就是负载很低的,CachedThreadPool,用少量的线程就可以满足低负载,不会给系统引入太大的压力;但是每天如果有少量的高峰期,比如说中午或者是晚上,高峰期可能需要一下子搞几百个线程出来,那么CachedThreadPool就可以满足这个场景;高峰期应付过去之后,线程如果处于空闲状态超过60s,自动回收空闲线程,避免给系统带来过大的负载

 

 

12、说一下该如何设置线程池的参数,设置多大合适?

(处理时间,如:100ms)* 任务总数(100) = 10(100个任务要10s)

如果想在1s内处理完 100 个任务,那就要有10个线程,如果想在2s内处理完,那就设置5个线程

  • 核心线程数可以考虑 一天请求量的平均值,算出来一个
  • 最大线程数,可以根据高峰时段的请求数,算出来一个
  • 超时间是一般设置60s左右就行
  • 队列的话,可以自己设置个有界队列ArrayBlockingQueue,如果使用无界队列容易内存溢出,配合自己写的handler策略
  • handler的话,可以自己实现这个接口,写一个自己类似降级的逻辑,传给线程池,比如说如果发生意外,队列满了,那就走handler里的逻辑,离线存储,(然后自己写个线程,扫描mysql的handler的那个表,执行)。

 

4核8G的虚拟机,100个线程就差不多了,cpu可能就快达到了70%,80%

 

 

13、线程池被关闭的方式有哪几种?

  • shutdown():调用之后不允许提交新的任务了,所有调用之前提交的任务都会执行,等所有任务执行完了,才会真正关闭线程池,这就是优雅的关闭方式

 

  • shutdownNow():返回还没执行的task列表,然后不让等待的task执行,尝试停止正在执行的task,非优雅关闭,强制关闭


http://chatgpt.dhexx.cn/article/u1p7jBDV.shtml

相关文章

Java 线程池原理及四种常用的线程池使用

推荐阅读&#xff1a;Java线程池实现原理及其在美团业务中的实践 文章目录 什么是线程池使用线程池的好处线程池的实现原理流程图分析源码分析 线程池的使用向线程池中提交任务newCachedThreadPoolnewFixedThreadPoolnewScheduledThreadPoolnewSingleThreadExecutor自定义线程池…

Tomcat线程池监控及线程池原理分析

目录 一、背景 二、tomcat线程池监控 三、tomcat线程池原理 四、总结 一、背景 我们都知道稳定性、高可用对于一个系统来讲是非常重要的&#xff0c;而为了保证系统的稳定性&#xff0c;我们一般都会进行各方面的监控&#xff0c;以便系统有任何异常情况时&#xff0c;开发人员…

Python学习:线程池原理及实现

传统多线程方案会使用“即时创建&#xff0c; 即时销毁”的策略。尽管与创建进程相比&#xff0c;创建线程的时间已经大大的缩短&#xff0c;但是如果提交给线程的任务是执行时间较短&#xff0c;而且执行次数极其频繁&#xff0c;那么服务器将处于不停的创建线程&#xff0c;销…

超详细的线程池原理解析

说明 线程池作为常用的并发工具重要性不言而喻&#xff0c;本文针对线程池进行了抽丝剥茧般的深入解析&#xff0c;希望大家看后会有帮助。 1 ThreadPoolExecutor结构关系图 2 参数结构 public ThreadPoolExecutor( int corePoolSize,//核心线程数量int maximumPoolSize,…

从简单代码入手,分析线程池原理

一、线程池简介 1、池化思想 在项目工程中&#xff0c;基于池化思想的技术应用很多&#xff0c;例如基于线程池的任务并发执行&#xff0c;中间件服务的连接池配置&#xff0c;通过对共享资源的管理&#xff0c;降低资源的占用消耗&#xff0c;提升效率和服务性能。 池化思想…

线程池原理与实现

目录 1. 线程池是什么 2. 线程池的优点&#xff1a; 3. 线程池的应用场景 4. 线程池的实现 4.1 线程池实现原理 4.2 线程池基本框架 4.3 结构体&#xff1a; 4.4 提供的接口 4.5 线程池测试代码 5 线程池提高demo thrd_pool.h thrd_pool.c main.c 运行结果 6 re…

线程池原理——高频面试题

1.高频面试题&#xff1a; 1.为什么使用线程池&#xff0c;优势是什么&#xff1b; 2.线程池如何使用&#xff1b; 3.线程池的几个重要的参数介绍&#xff1b; 4.线程池底层工作原理&#xff1b; 5.线程池用过吗&#xff1f;生产上你如何设置合理参数&#xff1b; 2.线程…

Android线程池原理详解

简介 但凡有点开发经验的同学都知道&#xff0c;频繁的创建和销毁线程是会给系统带来比较大的性能开销的。所以线程池就营运而生了。那么使用线程池有什么好处呢&#xff1f; 降低资源消耗 可以重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度 当任务到达时…

Java面试题之:线程池原理

Java面试题之&#xff1a;线程池原理 一、简介二、线程复用三、线程池的组成四、拒绝策略五、Java 线程池工作过程 一、简介 线程池做的工作主要是控制运行的线程的数量&#xff0c;处理过程中将任务放入队列&#xff0c;然后在线程创建后启动这些任务&#xff0c;如果线程数量…

ThreadPoolExecutor线程池原理

ThreadPoolExecutor线程池原理 线程池原理1. 线程池的简单介绍1.1 线程池是什么1.2 线程池解决的核心问题是什么 2. 线程池的实现原理2.1 线程池的执行流程2.2 源码分析 3. 线程池的使用3.1 线程池的创建3.2 向线程池提交任务3.3 生命周期管理3.4 关闭线程池3.5 合理地配置线程…

线程池原理分析

使用线程池目的 在开发过程中&#xff0c;合理地使用线程池能够带来3个好处。 1.降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 2.提高响应速度。当任务到达时&#xff0c;任务可以不需要等到线程创建就能立即执行。 3.提高线程的可管理性。线程是稀…

Java 线程池原理总结

Java 线程池原理总结 &#xff08;一&#xff09;什么是线程池 线程池做的工作主要是控制运行的线程的数量&#xff0c;处理过程中将任务放入队列&#xff0c;然后在线程创建后启动这些任务&#xff0c;如果线程数量超过了最大数量超出数量的线程排队等候&#xff0c;等其它线…

线程池原理总结

【引言】 关于线程池&#xff0c;印象中好像自己有写过相关的总结博客。翻了翻之前的博客&#xff0c;确实&#xff0c;在去年十一月写过一篇《线程池使用总结》。 时隔一年&#xff0c;我已经离开了那家让我成长很多的公司&#xff0c;在那里&#xff0c;写了很多的代码&…

线程池原理全解析

目录 1 线程池简介 2 线程池 2.1 ThreadPoolExecutor类 2.2 ThreadPoolExecutor方法 3 线程池实现原理 3.1.线程池状态 3.2.任务的执行 总结过程 3.3.线程池中的线程初始化 3.4.任务缓存队列及排队策略 3.5.任务拒绝策略 3.6.线程池的关闭 3.7.线程池容量的动态调…

一文带你清晰弄明白线程池的原理

不知道你是否还记得阿里巴巴的java代码规范中对多线程有这样一条强制规范: 【强制】线程资源必须通过线程池提供&#xff0c;不允许在程序中显示创建线程。 说明&#xff1a;使用线程池的好处是减少在创建和销毁线程池上所消耗的时间以及系统资源的开销&#xff0c;解决资源不足…

线程池工作原理

一、线程池默认工作流程 1、线程在有任务的时候会创建核心的线程数corePoolSize 2、当线程满了&#xff08;有任务但是线程被使用完&#xff09;不会立即扩容,而是放到阻塞队列中,当阻塞队列满了之后才会继续创建线程。 3、如果队列满了,线程数达到最大线程数则会执行拒绝策…

线程池的工作原理

线程池&#xff0c;就是存放线程的池子&#xff0c;池子里存放了很多可以复用的线程 作用&#xff1a; 1.对线程进行统一管理 2.降低系统资源消耗。通过复用已存在的线程&#xff0c;降低线程创建和销毁造成的消耗 3.提高响应速度。当有任务到达时&#xff0c;无需等待新线…

线程池核心原理分析

一、基础概念 线程池是一种多线程开发的处理方式&#xff0c;线程池可以方便得对线程进行创建&#xff0c;执行、销毁和管理等操作。主要用来解决需要异步或并发执行任务的程序 谈谈池化技术 简单点来说,就是预先保存好大量的资源,这些是可复用的资源,你需要的时候给你。对于…

线程池原理(讲的非常棒)

Java并发编程&#xff1a;线程池的使用 在前面的文章中&#xff0c;我们使用线程的时候就去创建一个线程&#xff0c;这样实现起来非常简便&#xff0c;但是就会有一个问题&#xff1a; 如果并发的线程数量很多&#xff0c;并且每个线程都是执行一个时间很短的任务就结束了&…

服务器常见的网络攻击以及防御方法

网络安全威胁类别 网络内部的威胁&#xff0c;网络的滥用&#xff0c;没有安全意识的员工&#xff0c;黑客&#xff0c;骇客。 木马攻击原理 C/S 架构&#xff0c;服务器端被植入目标主机&#xff0c;服务器端通过反弹连接和客户端连接。从而客户端对其进行控制。 病毒 一…