ThreadPoolExecutor

【信道编码/Channel Coding】线性分组码 这是本专栏信道编码/Channel Coding的第二站,想对信道编码有一个系统性的认识可以看本专栏的信道编码的整体框架一文。而在本篇文章中,将介绍线性分组码的基本原理。 阅读详情

ThreadPoolExecutor

线程池

1. 实例化

1.1 最终构造器

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.2 解读参数

  • corePoolSize 核心线程数,保持常活跃.
    • 当设置了allowCoreThreadTimeOut, 核心线程也会被释放
  • maximumPoolSize 当前线程池允许的最大线程数
  • keepAliveTime 线程数大于核心数(corePoolSize)时启用,多余的空闲线程在终止前等待新任务的最长时间
  • unit 时间单位,为 keepAliveTime 服务
  • workQueue 通过 execute 投递的任务将会放在这个队列中,慢慢消费(通过采用有界队列)
  • threadFactory 线程池创建新线程的工厂类
  • handler 当且仅当 maximumPoolSize 饱和和 workQueue 达到最大值时启用,定义如何处理新投递的任务

1.3 核心属性解读

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    private static final int COUNT_BITS = Integer.SIZE - 3;  //29
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    // 线程池的状态
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

    // 获取状态码
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
   // 获取正在运行的线程数
    private static int workerCountOf(int c)  { return c & CAPACITY; }
  • ctl 两种含义, 高三位表示线程池的状态, 低 29 位表示活跃的线程数量

2.任务投递关键方法

2.1 execute

往线程池中提交任务,也是整个线程池最关键的方法

2.1.1 源码
public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        
        int c = ctl.get();
  // 线程数是否小于核心数
        if (workerCountOf(c) < corePoolSize) {
          // 创建核心线程并运行
            if (addWorker(command, true))
                return;  // 投递成功直接结束
            c = ctl.get();
        }
  // 线程池运行中, 尝试添加到缓存队列
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
          // 二次判断线程池是否运行, 若没有则移除任务,并触发拒绝策略
            if (! isRunning(recheck) && remove(command))
                reject(command);
          // 缓存队列添加成功了, 判断工作线程是不是空的, 是就创建一个非核心线程
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
  // 队列添加失败(一般是队列满了), 尝试创建新的非核心线程来运行
        else if (!addWorker(command, false))
          // 执行拒绝策略, 调用 rejectedExecution 方法
            reject(command);
    }
2.1.2 流程图
graph TB A(execute中投递任务) Z(投递完成) B{判断核心数是否满了} A--->B D[尝试创建核心线程来运行] B--没有-->D B-->是-->F E{是否成功} D--->E E--是-->Z F[将任务丢进任务队列] E--否-->F G{是否成功} F--->G I[当工作线程为0,创建一个非核心线程] G--是-->I I-.->Z H[尝试创建非核心线程运行] G==否==>H J{创建是否成功} H-->J J--是-->Z K[执行拒绝策略] J--否-->K

由流程看出: 任务优先度是 coreThread -> workQueue -> maximumPoolSize ->

RejectedExecutionHandler(过程中出现异常或者线程池非运行状态都会运行)

2.2 addWorker

两个参数, Runnable firstTask, boolean core

创建新的线程的入口方法

  • firstTask 创建新线程是投的的任务,可为null
  • core 是否是核心线程
  1. 判断线程池是否将要关闭了,是直接返回 false
  2. 判断工作线程数是否大于等于核心线程数或者总的线程数, 是直接false
  3. 工作线程数数加1
  4. 调用 threadFactory 创建线程,并将其放到 works 线程池中
  5. 放入成功则直接启动线程, 否则线程数减1

3. 拒绝策略

默认提供了4种

  • AbortPolicy 直接抛出异常, 默认的就是中,通过6个参数的构造函数可看到
  • CallerRunsPolicy 让投递这个任务的线程自己去执行这个任务
  • DiscardPolicy 直接丢弃刚刚投递进来的任务, 什么也不做
  • DiscardOldestPolicy 从队列中放弃最早投进去的任务,将新任务加进去

4. 几种常见的队列

注意使用无边界的队列,容易内存溢出

  • PriorityBlockingQueue优先级阻塞队列, 无边界. 队列会根据优先级排序
  • LinkedBlockingQueue 链表,通过构造器限定队列大小, 默认 Integer.MAX
  • SynchronousQueue 可认为队列大小为1, 放入必须有人take
  • ArrayBlockingQueue 基于数组的队列, 内部维护了一个putIndex,达到环形数组的效果
零基础学写《扫雷》游戏(Qt扫雷源码) 扫雷游戏是在windows系统中自带的游戏,他的游戏玩法其实很简单,20世纪初期电脑上没有啥游戏可以玩,所以扫雷游戏也算是当时是最常火爆的一个电脑游戏。以下文章详细介绍扫雷游戏的实现。实现语言为C++。 阅读详情

相关推荐

新手避坑指南:用COMSOL Multiphysics仿真气体放电(汤逊vs.流注)

本文详细介绍了使用COMSOL Multiphysics仿真气体放电的实战指南,涵盖汤逊理论和流注模型的实现方法。通过对比两种放电模型的关键参数和物理场配置,帮助新手避免常见错误,准确预测气体击穿过程。文章还提供了工程应用案例,如高压绝缘子设计优化,展示了仿真技术在电力设备绝缘设计中的实际价值。

weixin_28716181的博客 473

ThreadPoolTaskExecutor和ThreadPoolExecutor

注意关系3是针对的有界队列,无界队列永远都不会满,所以只有前2种关系。

学习不止境的博客 1万+

TSMaster如何用珠海创芯CAN卡实现高效CAN通信(附完整驱动安装指南)

本文详细介绍了如何使用TSMaster软件与珠海创芯CAN卡实现高效CAN通信,包括驱动安装、系统配置、ControlCAN.dll替换及TSMaster集成配置等关键步骤。通过实战指南和故障排除技巧,帮助工程师快速搭建稳定可靠的CAN通信测试环境,适用于汽车电子和工业控制等领域。

weixin_29201859的博客 481

ThreadPoolExecutor详解

一、ThreadPoolExecutor类讲解 1、线程池状态: 五种状态: 线程池的状态 说明 RUNNING 允许提交并处理任务 SHUTDOWN 不允许提交新的任务,但是会处理完已提交的任务 STOP 不允许提交新的任务,也不会处理阻塞队列中未执行的任务, 并设置正在执行的线程的中断标志位 TIDYING .

赶路人儿 11万+

oracle rac 成本及架构,Oracle Extended RAC 架构实战

Extended-RAC,是RAC技术的一种扩展增强。Extended-RAC是通过专用光纤(或租用裸光纤)加DWDM(波分设备)设备将两个不同楼栋/同城甚至异地机房进行相连,将数据库主机、存储分别放置于不同机房,利用存储复制/ASM Mirror等技术进行数据复制进行搭建的一种远距离集群架构。Extended RAC需要将不同楼栋/同城甚至异地机房通过专用光纤(或租用裸光纤)加DWDM(光纤复用...

weixin_33812391的博客 2453

DCMM评估报告模板样例

这篇DCMM评估报告对某数据管理公司2020年的数据管理能力进行了全面分析。报告显示,该公司在数据战略方面取得初步进展,但在数据治理和数据架构方面仍存在明显不足,包括缺乏有效治理流程、数据质量监控不足,以及数据标准化和转换灵活性不足等问题。评估报告提出了针对性改进建议,包括完善数据战略、建立治理流程、加强质量监控和提升数据转换灵活性等,为提升数据管理成熟度提供了重要指导。

cdfunlove的博客 166

Python ThreadPoolExecutor线程池

概念 Python中已经有了threading模块,为什么还需要线程池呢,线程池又是什么东西呢?以爬虫为例,需要控制同时爬取的线程数,例子中创建了20个线程,而同时只允许3个线程在运行,但是20个线程都需要创建和销毁,线程的创建是需要消耗系统资源的,有没有更好的方案呢?其实只需要三个线程就行了,每个线程各分配一个任务,剩下的任务排队等待,当某个线程完成了任务的时候,排队任务就可以安排给这个线程继续执行。 这就是线程池的思想(当然没这么简单),但是自己编写线程池很难写的比较完美,还需要考虑复杂情况下的线程

GMH的博客 2万+

ansys 求解过程中出现未知错误。检查“求解信息”对象上的“求解器输出”,查找可能的原因。-静力学分析遇到的,这是什么原因——An unknown error occurred ——未找到解决方法

点击“确定”关闭弹窗后,进入Workbench的‌“求解信息”对象‌,查看‌“求解器输出”‌,搜索“Error”“Fatal”“Warning”等关键词,找到具体的错误描述,比如材料未定义、网格质量问题、内存不足等,这是精准解决问题的关键。进入“工具-选项-mechanical APDL”,取消勾选“分布式”,GPU加速器选择“none”。在“求解进程设置-高级”中调整内存分配参数,或切换为迭代求解器(如PCG求解器),它更省内存。尝试简化模型,比如删除非关键细节、合并重复部件,分步验证模型,定位问题源。

qq_15963745的博客 609

Java ThreadPoolExecutor的拒绝策略

一、概述 在分析ThreadPoolExecutor的构造参数时,有一个RejectedExecutionHandler参数。 RejectedExecutionHandler是一个接口: public interface RejectedExecutionHandler { void rejectedExecution(Runnable r, ThreadPoolExecu...

悟鸣的技术博客 6686

深度学习图神经网络 (GNN) —— 处理图结构数据(六十九)

本文系统介绍了图神经网络(GNN)的核心概念、主流模型及其应用。主要内容包括: GNN基础:阐述了图结构数据的特性(节点数不定、连接不规则),以及GNN相比CNN/RNN的优势在于处理非欧式空间的图数据。 核心机制:重点讲解了消息传递框架(MPNN),通过聚合邻居信息迭代更新节点表示,并分析了GCN的归一化邻接矩阵计算和GAT的注意力权重机制。 典型模型: GCN:基于归一化邻接矩阵的特征传播 GAT:引入注意力机制区分邻居重要性 GraphSAGE:通过采样解决大图扩展性问题 GIN:理论表达能力最强的图

hello.reader 300

ardupilot 获取避障传感器数据

本节主要记录自己学ardupilot的避障代码过程,首先看下怎么注册避障传感器,然后怎么获取避障数据。

陌城烟雨 5524

Python中ThreadPoolExecutor的使用

Python中ThreadPoolExecutor的使用

qq_56447863的博客 3299

【原创】下载RealEstate10K数据集原始视频的方法

目前互联网上能搜到下载RealEstate10K数据集原始视频的方法都已经不能用了,这篇博客介绍一种目前可用的下载RealEstate10K数据集原始视频的方法,并给出自动化的脚本代码。

沉迷单车的追风少年 2462

ForkJoinPool和ThreadPoolExecutor区别

ForkJoinPool和ThreadPoolExecutor的主要区别体现在任务执行的方式和适用的场景上。

刘皇叔说Java的博客 2144

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【Executors和ThreadPoolExecutor】

"Executors"和"ThreadPoolExecutor"都是Java中的并发工具类,都是用来创建和管理线程池的。"Executors"是一个工厂类,它提供了创建线程池的静态方法,包括newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor、newScheduledThreadPool等,这些方法可以创建不同类型的线程池。

学习愚公的博客 1384

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

ThreadPoolExecutor 详解

这是一个基于Flowable引擎(支持java、.NET),已支持MySQL、SqlServer、Oracle、PostgreSQL、DM(达梦)、 KingbaseES(人大金仓)6个数据库,支持私有化部署,前后端封装了上千个常用类,方便扩展,框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用。SynchronousQueue:直接传递队列(不存储任务,任务直接交给线程处理)。直接传递队列(SynchronousQueue):任务不存储,直接交给线程处理,适合高吞吐场景。

pantouyuchiyu的博客 858

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Executors和ThreadPoolExecutor详解

概述 在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了资源的开销。而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式,这一方面是由于jdk中Executor框架虽然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool().

川子的博客 4673

ThreadPoolExecutor 相关知识总结

ThreadPoolExecutor 参数详解、正确使用方法、运行原理总结

woniu_buhui_fei的博客 406

ThreadPoolTaskExecutor 和 ThreadPoolExecutor 的区别

ThreadPoolExecutor是Java原生的线程池类,而ThreadPoolTaskExecutor是Spring推出的线程池工具 一、从核心参数看两者关系 ThreadPoolExecutor(java.util.concurrent) public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAl.

weixin_50604409的博客 7965

ThreadPoolExecutor的源码解析

011:代表TERMINATED状态,这个状态是TIDYING状态转换过来的转换过来只需要执行一个terminated方法。解释: 如果工作线程个数小于核心线程数,满足要求,添加核心工作线程。上述条件都不符合,直接直接执行决绝策略,结束。提交的任务不能为null,否则抛空指针异常。(任务,是核心线程吗): 是否添加工作线程。是提交任务到线程池的核心方法,:是提交任务到线程池的核心方法。(上述的步骤都失败,走下面的)方法,将任务添加到阻塞队列。套了一层,进行运算时,是。,正在处理任务的线程会。

aristo 907

Python的线程池之ThreadPoolExecutor

线程池ThreadPoolExecutor ThreadPoolExecutor位于python3标准库的并发包(concurrent.futures)下,特点 主线程可以获取某一个线程的状态,以及返回值。 线程同步 让多线程和多进程的编码接口一致。 简单粗暴...

张小洛的BOLG 7758

ThreadPoolExecutor、ExecutorService 区别

实际上使用的时候一般都是声明ThreadPoolExecutor,然后封装成ExecutorService返回。是两个核心但功能层级不同的组件,ExecutorService。两个使用起来没区别,一个是具体的实现类,一个是抽象类。类似于ArrayList和List的区别。// monitor监控。// xxxxx线程池。在Java并发编程中,

Java杂谈 920

ThreadPoolExecutor原理详解

增加线程是通过线程池中的addWorker方法,该方法的功能就是增加一个线程,该方法不考虑线程池是在哪个阶段增加的该线程,这个分配线程的策略是在上个步骤完成的,该步骤仅仅完成增加线程,并使它运行,最后返回是否成功这个结果。线程池运行的状态,并不是用户显式设置的,而是伴随着线程池的运行,由内部来维护。任务拒绝模块是线程池的保护部分,线程池有一个最大的容量,当线程池的任务缓存队列已满,并且线程池中的线程数目达到maximumPoolSize时,就需要拒绝掉该任务,采取任务拒绝策略,保护线程池。

m0_74219798的博客 1444

Java中ThreadPoolExecutor的使用

Java中ThreadPoolExecutor的参数以及使用、预热

weixin_45215156的博客 1112

python threadpoolexecutor_Python线程池之ThreadPoolExecutor详解

1、什么是线程池线程池的基本思想是一种对象池,在程序启动时就开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。2、使用线程池的好处减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。运用线程池能有效的控制线程最大并发数,可以根...

weixin_39967096的博客 2008
上一篇: springBoot2 整合activemq
下一篇: mysql安转
董董先生
博客等级 码龄10年 70粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值