线程池核心九问

2023-11-03 03:10
文章标签 线程 核心 九问

本文主要是介绍线程池核心九问,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.什么是线程池?

线程池就是提前创建若干个线程,
如果有任务需要处理,线程池里的线程就会处理任务,处理完之后线程并不会被销毁,而是等待下一个任务。减少频繁创建和销毁线程消耗系统资源。

2.为什么要用线程池 ?

频繁创建、销毁 线程,将是对系统资源的极大浪费。
因此,实际开发中我们将使用线程池来管理、复用线程。
使用线程池,可以
1.降低资源消耗: 重复利用线程,减少创建和销毁造成的消耗。
2.提升响应速度: 任务到达,不需要创建,立即执行。
3.提高可管理型: 线程是CPU调度和分派的基本单位,
如果无限制地创建,不仅会消耗系统资源,还会降低系统稳定性。
使用线程池可以统一进行 分配、调优和监控。

3.创建线程池的方式?

Java从1.5 Executors 类提供四种创建线程池方式
1).newSingleThreadExecutor()

  • 单个线程的线程池,即线程池中每次只有一个线程工作,单线程串行执行任务,(队列长度-Integer.MAX_VALUE)

2).newFixedThreadPool(maximumPoolSize)

  • **定最大线程数,线程池 **,核心线程数=最大线程数=设置的线程数,可控制线程最大并发数,(队列长度-Integer.MAX_VALUE);

3).newCachedThreadPool()

  • 可缓存线程池,有任务才新建线程,闲置线程保存60秒 ,(最大线程数长度-Integer.MAX_VALUE)

4).newScheduledThreadPool(corePoolSize)

  • 定核心线程数,线程池,支持定时及周期性任务执行。(最大线程数长度-Integer.MAX_VALUE)
    在这里插入图片描述

在这里插入图片描述

4.为什么不建议使用 Executors静态工厂构建线程池

主要原因:队列堆积,有OOM风险
1.FixedThreadPool 和 SingleThreadPool
允许的请求队列(底层实现是LinkedBlockingQueue)长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM

2.CachedThreadPool 和 ScheduledThreadPool
允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

5.线程池参数

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) { }

corePoolSize:核心线程数量,一直存在,除非 allowCoreThreadTimeOut设置为true
maximumPoolSize:线程池允许的最大线程池数量 10
keepAliveTime:线程数量超过corePoolSize,空闲线程的最大超时时间
unit:超时时间的单位
workQueue:工作队列,保存未执行的Runnable 任务 (BlockingQueue 的实现类)
threadFactory:创建线程的工厂类
handler:当线程已满,工作队列也满了的时候,会被调用。被用来实现各种拒绝策略。

工作队列介绍
在这里插入图片描述

6.线程池的执行顺序

在这里插入图片描述

当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运
行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它
最终会收缩到 corePoolSize 的大小。

7.四种策略**

  • ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常
  • ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
  • ThreadPoolExecutor.DiscardOldestPolicy:**丢弃队列最老的任务,然后重新提交被拒绝的任务 **
  • ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务

8.实现原理

线程池由两个核心数据结构组成:
1)线程集合(workers):存放执行任务的线程,是一个HashSet;
2)任务等待队列(workQueue):存放等待线程池调度执行的任务,是一个阻塞式队列BlockingQueue;

8.如何合理设置线程池大小

任务一般可分为:CPU密集型、IO密集型、混合型,对于不同类型的任务需要分配不同大小的线程池。

  • CPU密集型任务: 尽量使用较小的线程池,一般为CPU核心数+1 ; (+1是利用等待空闲)
    • 因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,只能增加上下文切换的次数,因此会带来额外的开销。
  • IO密集型任务: 一般为2*CPU核心数。
    • IO密集型任务CPU使用率并不高,因此可以让CPU在等待IO的时候去处理别的任务,充分利用CPU时间。
  • 混合型任务
    • 可以将任务分成IO密集型和CPU密集型任务,然后分别用不同的线程池去处理。

线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。
最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目

//java 中获取核心数 int availableProcessors = Runtime.getRuntime().availableProcessors();

9.线程池的动态规划参数动态化

JDK原生线程池ThreadPoolExecutor提供了如下几个public的setter方法,如下图所示:
在这里插入图片描述

JDK允许线程池使用方通过ThreadPoolExecutor的实例来动态设置线程池的核心策略,
以setCorePoolSize为方法例,
在运行期线程池使用方调用此方法设置corePoolSize之后,
线程池会直接覆盖原来的corePoolSize值,并且基于当前值和原始值的比较结果采取不同的处理策略。
对于当前值小于当前工作线程数的情况,说明有多余的worker线程,
此时会向当前空闲的worker线程发起中断请求以实现回收,
多余的worker在下次空闲的时候也会被回收;
对于当前值大于原始值且当前队列中有待执行任务,
则线程池会创建新的worker线程来执行队列任务,setCorePoolSize具体流程如下:
在这里插入图片描述

这篇关于线程池核心九问的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/335174

相关文章

Java中如何正确的停掉线程

《Java中如何正确的停掉线程》Java通过interrupt()通知线程停止而非强制,确保线程自主处理中断,避免数据损坏,线程池的shutdown()等待任务完成,shutdownNow()强制中断... 目录为什么不强制停止为什么 Java 不提供强制停止线程的能力呢?如何用interrupt停止线程s

python 线程池顺序执行的方法实现

《python线程池顺序执行的方法实现》在Python中,线程池默认是并发执行任务的,但若需要实现任务的顺序执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录方案一:强制单线程(伪顺序执行)方案二:按提交顺序获取结果方案三:任务间依赖控制方案四:队列顺序消

Python进阶之列表推导式的10个核心技巧

《Python进阶之列表推导式的10个核心技巧》在Python编程中,列表推导式(ListComprehension)是提升代码效率的瑞士军刀,本文将通过真实场景案例,揭示列表推导式的进阶用法,希望对... 目录一、基础语法重构:理解推导式的底层逻辑二、嵌套循环:破解多维数据处理难题三、条件表达式:实现分支

深度解析Python yfinance的核心功能和高级用法

《深度解析Pythonyfinance的核心功能和高级用法》yfinance是一个功能强大且易于使用的Python库,用于从YahooFinance获取金融数据,本教程将深入探讨yfinance的核... 目录yfinance 深度解析教程 (python)1. 简介与安装1.1 什么是 yfinance?

SpringBoot实现虚拟线程的方案

《SpringBoot实现虚拟线程的方案》Java19引入虚拟线程,本文就来介绍一下SpringBoot实现虚拟线程的方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录什么是虚拟线程虚拟线程和普通线程的区别SpringBoot使用虚拟线程配置@Async性能对比H

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

Linux线程同步/互斥过程详解

《Linux线程同步/互斥过程详解》文章讲解多线程并发访问导致竞态条件,需通过互斥锁、原子操作和条件变量实现线程安全与同步,分析死锁条件及避免方法,并介绍RAII封装技术提升资源管理效率... 目录01. 资源共享问题1.1 多线程并发访问1.2 临界区与临界资源1.3 锁的引入02. 多线程案例2.1 为

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

Java中的xxl-job调度器线程池工作机制

《Java中的xxl-job调度器线程池工作机制》xxl-job通过快慢线程池分离短时与长时任务,动态降级超时任务至慢池,结合异步触发和资源隔离机制,提升高频调度的性能与稳定性,支撑高并发场景下的可靠... 目录⚙️ 一、调度器线程池的核心设计 二、线程池的工作流程 三、线程池配置参数与优化 四、总结:线程