【线程池的使用规范、线程池的7个参数、4种拒绝策略、线程池的5种状态、线程池的执行流程】

news2025/1/13 15:58:07

在这里插入图片描述

一.线程池的使用规范

阿里巴巴开发手册规定,线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让开发人员更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:

  1. FixedThreadPool 和 SingleThreadPool:
    允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
  2. CachedThreadPool:
    允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

二.线程池的7个参数你都知道吗?

构造方法中的参数信息
在这里插入图片描述
查看源代码

/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
  1. corePoolSize 线程池核心线程大小

线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。任务提交到线程池后,首先会检查当前线程数是否达到了corePoolSize,如果没有达到的话,则会创建一个新线程来处理这个任务。

  1. maximumPoolSize 线程池最大线程数量

当前线程数达到corePoolSize后,如果继续有任务被提交到线程池,会将任务缓存到工作队列(后面会介绍)中。如果队列也已满,则会去创建一个新线程来出来这个处理。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。

  1. keepAliveTime 空闲线程存活时间

一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定

  1. unit 空闲线程存活时间单位

keepAliveTime 空闲线程存活时间计量单位
在这里插入图片描述

  1. workQueue 工作队列
    新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。jdk中提供了四种工作队列:
    在这里插入图片描述
    ①ArrayBlockingQueue
    1.基于数组的有界阻塞队列,按FIFO排序。
    2.新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。
    3.当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。
    4.如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。
    在这里插入图片描述

②LinkedBlockingQuene
1.基于链表的无界阻塞队列(最大容量为Interger.MAX),按照FIFO排序。
2.由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而基本不会去创建新线程直到maxPoolSize(很难达到Interger.MAX这个数)。
3.使用该工作队列时,参数maxPoolSize其实是不起作用的。
在这里插入图片描述

③SynchronousQuene
1.一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。
2.新任务进来时,不会缓存,直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。
在这里插入图片描述

④PriorityBlockingQueue
1.具有优先级的无界阻塞队列。
2.优先级通过参数Comparator实现。
在这里插入图片描述

  1. threadFactory 线程工厂
    创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等操作。
    在这里插入图片描述

  2. handler 拒绝策略
    当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,我们通过拒绝策略来解决这个问题,jdk中提供了4中拒绝策略:
    在这里插入图片描述
    ①CallerRunsPolicy
    该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务。
    在这里插入图片描述

②AbortPolicy
该策略下,直接丢弃任务,并抛出RejectedExecutionException异常。
在这里插入图片描述

③DiscardPolicy
该策略下,直接丢弃任务,什么都不做。
在这里插入图片描述

④DiscardOldestPolicy
该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列
在这里插入图片描述

三.线程池的5种状态

在这里插入图片描述

  1. RUNNING

    • 线程池被创建,线程池的状态就是RUNNING状态;
    • 线程池处于RUNNING状态时,线程池能够接收新任务,也能够对已经添加的任务进行处理;
  2. SHUTDOWN

    • 线程池已经被关闭了,不再接收新任务;但是,其还是会处理队列中的剩余的任务;
    • 调用线程池的shutdown()方法后,线程池的状态就会由RUNNING转为SHUTDOWN;
  3. STOP

    • 线程池处于STOP状态,此时线程池不再接收新任务,不处理已经添加进来的任务,并且会中断正在处理的任务;
    • 调用线程池的shutdownNow()方法后,线程池的状态就会由RUNNING或SHUTDOWN转为STOP;
  4. TIDYING

    • 线程池被下达关闭命令后,如果当前所有的任务都已经终止了(这个终止可以表示执行结束,也可以表示强制中断,也可以表示被丢弃) ,那么线程就会进入TIDYING状态;当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
    • 如果线程状态已经是SHUTDOWN了,并且线程中以及队列中都没有任务时,线程池就会由SHUTDOWN转为TIDYING;如果线程池状态为STOP,那么当线程池把所有的任务都给清理干净时,线程池就会由STOP转为TIDYING;
  5. TERMINATED;

    • 线程池结束,不能重新启动了;
    • 如果线程池处于TIDYING状态,那么当线程池执行完terminated()方法后,线程池状态就会由TIDYING转为TERMINTED;

四.线程池的执行流程

  1. 提交任务后会首先进行当前工作线程数与核心线程数的比较,如果当前工作线程数小于核心线程数,则直接调用 addWorker() 方法创建一个核心线程去执行任务;

  2. 如果工作线程数大于核心线程数,即线程池核心线程数已满,则新任务会被添加到阻塞队列中等待执行,当然,添加队列之前也会进行队列是否为空的判断;

  3. 如果线程池里面存活的线程数已经等于核心线程数了,且阻塞队列已经满了,再会去判断当前线程数是否已经达到最大线程数 maximumPoolSize,如果没有达到,则会调用 addWorker() 方法创建一个非核心线程去执行任务;

  4. 如果当前线程的数量已经达到了最大线程数时,当有新的任务提交过来时,会执行拒绝策略

在这里插入图片描述

五.总结

学习不仅输入,还要输出,接下来我们一起来回顾一下这篇文章的内容吧

  1. 线程池的使用规范
  2. 线程池的7的参数
  3. 线程池的4种拒绝策略
  4. 线程池的5种状态
  5. 线程池的执行流程

好了,具体的细节没有想起来的可以翻上去看看,这篇文章就学习到这里,接下来我们一起来学习关于多线程相关的知识。

你准备好了吗?来吧在这里插入图片描述

我是硕风和炜,我们下篇文章见哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/379408.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EndNote20 自动生成毕业论文参考文献

软件版本&#xff1a; EndNote 20 字体&#xff1a;Chinese Standard GB/T 7714 去谷歌学术下载Endnote格式的enw文件 在EndNote中 File>New… 新建Libaray Tools>Output Styles>Open Style Manager… 勾选Chinese std GBT7714(numeric) Tools>Output Styles>…

CSS背景属性之颜色渐变

颜色渐变 颜色渐变其实在网页设计中并不是特别常见&#xff0c; 但也不可避免的会出现导航栏是渐变色这种情况或者别的不是单一颜色的情况&#xff0c; 例如&#xff1a;这样的设计解决方案并不是只可以使用颜色渐变&#xff0c;我们可以使用两个div拼接&#xff0c;将文字放…

如果坚定了想要进入网络安全领域的决心,应该怎样学习呢?

1、建立科学的学习路径 如果你原本从事程序开发&#xff0c;可以选择Web安全/渗透测试方向入门&#xff0c;一是市场需求量高&#xff0c;二则是发展相对成熟&#xff0c;入门比较容易。一定要根据自身的知识结构建立科学的学习路径&#xff0c;只有学到一定程度、或者有了一定…

Function Mesh:流处理任务的 Serverless 化实践

文章摘要本文整理自 ApacheCon Asia 上&#xff0c;StreamNative 工程师付睿的分享《Use Apache Pulsar Functions in a Cloud-Native way》。本文将介绍在云原生环境中使用 Pulsar Functions 的实践&#xff0c;以及基于 Pulsar Functions 和 Kubernetes 的项目 Function Mesh…

Redis实现高可用

怎么实现Redis的高可用&#xff1f;我们在项目中使用Redis&#xff0c;肯定不会是单点部署Redis服务的。因为&#xff0c;单点部署一旦宕机&#xff0c;就不可用了。为了实现高可用&#xff0c;通常的做法是&#xff0c;将数据库复制多个副本以部署在不同的服务器上&#xff0c…

tensorflow2.4--1.框架介绍

前言 虽然1.x版本tensorflow有很多项目都基于此构建&#xff0c;然而随着2.x版本的推出&#xff0c;很多架构已经发生了改变&#xff0c;代码发生了改变&#xff0c;同时很多模组已经废弃不用或者更新,tensorflow1.x已经不能再兼容最新的项目,与时俱进是必要的&#xff0c;因此…

【图像处理】数字图像处理基础(分辨率,像素,显示...)

Table of Contents1.数字图像处理基础1.1 图像表示1.1.1 图像成像模型1.1.2 数字图像的表示a.图像采样b.图像灰度的量化c.算比特数1.2 分辨率1.2.1 空间分辨率1.2.2 灰度分辨率1.3 像素间的关系1.3.1 像素邻域a.4邻域b.4对角邻域c.8邻域1.3.2 像素邻接1.3.3 像素连通1.3.4 像素…

【C语言航路】第十五站:程序环境和预处理

目录 一、程序的翻译环境和执行环境 二、编译和链接 1.翻译环境 2.编译本身也分为几个阶段 3.运行环境 三、预处理 1.预定义符号 2.#define 1.#define定义标识符 2.#define定义宏 3.#define 替换规则 4.#和## 5.带副作用的宏参数 6.宏和函数的对比 7.命名约定 …

Android Qcom Display学习(十二)

该系列文章总目录链接与各部分简介&#xff1a; Android Qcom Display学习(零) 本章主要是基于高通平台上dump出GPU渲染 or GPU合成 or HWC合成的GraphicBuffer的数据。 起初是在B站上看到这么一个视频&#xff0c;能dump出每个Layer的数据显示系统原理以及图形系统调试&#…

Delphi 中 FireDAC 数据库连接(设置选项)

描述了为什么选项集使FireDAC成为一个灵活的数据库框架以及如何使用这些选项。FireDAC提供了大量的选项&#xff0c;这些选项被组织成一个分层的选项系统,大多数选项可以保留其默认值。一、议题TopicDescription数据类型映射FireDAC提供了一个灵活的可调整的数据类型映射系统&a…

command-line变成-bash-4.2

故障描述&#xff1a; 故障诊断&#xff1a; 分析用户创建的过程&#xff1a; Useradd jfedu1命令默认创建用户jfedu1&#xff0c;会根据如下步骤进行操作&#xff1a; 读取/etc/default/useradd&#xff0c;根据配置文件执行创建操作&#xff1b; 在/etc/passwd文件中添加…

Python 之 Pandas merge() 函数、set_index() 函数、drop_duplicates() 函数和 tolist() 函数

文章目录一、merge() 函数1. inner2. left 和 right3. outer二、set_index() 函数三、drop_duplicates() 函数四、tolist() 函数五、视频数据分析案例1. 问题要求2. 解决过程在最开始&#xff0c;我们先导入常规的 numpy 和 pandas 库。 import numpy as np import pandas as …

【数据挖掘】2、数据预处理

文章目录一、数据预处理的意义1.1 缺失数据1.1.1 原因1.1.2 方案1.1.3 离群点分析1.2 重复数据1.2.1 原因1.2.2 去重的方案1.3 数据转换1.4 数据描述二、数据预处理方法2.1 特征选择 Feature Selection2.2 特征提取 Feature Extraction2.2.1 PCA 主成分分析2.2.2 LDA 线性判别分…

四维地球2.0上线,中国四维遥感云平台布局初见端倪

‍数据智能产业创新服务媒体——聚焦数智 改变商业近日&#xff0c;土耳其大地震一直备受全球各国人民的关注&#xff0c;为了在黄金72小时内帮助解救受困人员&#xff0c;包括中国在内的不少国家纷纷向土耳其政府和人民伸出援手&#xff0c;除了派出专业的救援队伍之外&#…

数据结构前提知识

数据结构数据结构 个体的存储个体关系的存储算法对存储数据的操作程序数据结构算法衡量算法的标准时间复杂度&#xff1a;注意不是程序执行的时间&#xff0c;因为一个程序执行的时间取决于软硬件环境&#xff0c;不同的机器&#xff0c;执行的速度不一样&#xff0c;配置好的…

【Unity】P2 基础操作

Unity基础操作移动、旋转与缩放移动方法一&#xff1a;xyz移动方法二&#xff1a;平面移动方法三&#xff1a;直接调整xyz的position三值进行调整旋转方法一&#xff1a;选择旋转按键并旋转方法二&#xff1a;按住CTRL再进行旋转操作&#xff0c;每次15度方法三&#xff1a;通过…

工作中单例模式用法及其使用场景?

前言 最近工作中有这么一个需求&#xff0c;我们系统出单后&#xff0c;需要同步数据到合作方&#xff0c;合作方对数据接收并解析反馈结果文件给我们&#xff0c;根据结果文件状态判断合作方系统是否解析成功&#xff0c;对于失败的单子&#xff0c;需要邮件通知相关负责人。…

微服务实战02-EurekaServer注册中心

EurekaServer &#xff0c;它扮演的角色是注册中心&#xff0c;用于注册各种微服务&#xff0c;以便于其他微服务找到和访问。 1、Eureka是什么 Eureka是Netflix的一个子模块&#xff0c;也是核心模块之一。Eureka是一个基于REST的服务&#xff0c;用于定位服务&#xff0c;以…

AUTOSAR为啥要开发新的社区商业模式?

总目录链接>> AutoSAR入门和实战系列总目录 文章目录1 自适应平台架构中的集群更新1.1 ara::diag 服务&#xff08;诊断&#xff09;更新1.2 信号到服务映射和自动驾驶接口让我们讨论一下信号到服务映射服务:Automated Driving Interface:2 车载应用商店概念本文介绍Re…

【RabbitMQ笔记09】消息队列RabbitMQ之常见方法的使用

这篇文章&#xff0c;主要介绍消息队列RabbitMQ之常见方法的使用。 目录 一、消息队列常见方法 1.1、连接工厂ConnectionFactory 1.2、连接Connection 1.3、通道Channel 1.4、交换机相关方法 &#xff08;1&#xff09;exchangeDeclare()声明交换机 1.5、队列相关方法 …