并发编程----4.java并发包中线程池的原理研究

2023-11-19

并发编程----4.java并发包中线程池的原理研究

java并发包中线程池ThreadPoolExecutor的原理研究

线程池的优点:线程的复用,减少线程创建和销毁带来的消耗;提供了一种资源限制和线程管理的手段,比如限制线程的个数和动态新增线程等。线程池继承 AbstractExecutorService

介绍
  1. ctl:原子变量,用来记录线程中的线程池状态和线程个数,类似于ReentrantReadWriteLock使用一个变量state保存两种信息

    1. 高三位表示线程池的状态(Integer 32位)
    2. 29位记录线程池的个数
  2. 线程池的状态

    1. shutdown:拒绝新的任务但是处理阻塞队列中的任务
    2. stop:拒绝新任务并且抛弃阻塞队列中的任务,同时中断正在处理的任务
    3. tidying:所有的任务执行完了之后包括阻塞队列中的线程,将调用terminated
    4. terminated:终止状态
    5. running:接受任务并且处理阻塞队列中的任务
  3. 线程状态转化

    1. running–>shutdown
    2. runining/shutdown–>stop
    3. shutdown–>tidying
    4. stop–>tidying
    5. tidying–>terminated
  4. 线程池参数

    1. corePoolSize: 线程池核心线程数
    2. workQueue: 用于保存等待执行任务的阻塞队列,例如:数组有界ArrayBlockingQueue、基于链表的LinkedBlockingQueue、最多一个元素的SynchronousQueue,优先队列PriorityBlockingQueue
    3. maximunPoolSize:线程池最大线程数量
    4. ThreadFactory:创建线程工厂
    5. RejectedExecutionHandler:饱和策略,当队列满且线程数达到MaximumPoolSize后采取的策略,比如抛出异常,AbortPolicy;CallerRunsPolicy调用者所在的线程运行任务。DiscardOldestPolicy丢弃一个任务执行当前任务。DiscardPolicy默默抛弃不抛出异常
    6. keeyAliveTime:存活时间,当前线程比核心线程多,并且处于闲置状态,则这些闲置的线程能存活最大时间
  5. 线程池类型

    1. newFixedThreadPool
      1. 创建一个核心数和最大线程数都为n的线程池,并且阻塞队列为Integer.MAX_VALUE。keekAliveTime=0说明线程个数比核心线程多并且空闲则回收
    2. newSingleThreadExecutor
      1. 创建一个核心数和最大线程数都为1的线程池,并且阻塞队列为Integer.MAX_VALUE。keekAliveTime=0说明线程个数比核心线程多并且空闲则回收
    3. newCacheThreadPool
      1. 按需创建线程的线程池,初始线程个数为0.最多线程数为Integer.MAX_VALUE,并且阻塞队列为同步队列,keepAliveTime=60说明只要任务只要在60s内就被回收。当加入同步任务就会马上被执行,同步队列中最多只有一个任务
        在这里插入图片描述
  6. mainLock为独占锁,用来控制新增worker线程操作原子性,termination是该锁对应的条件队列,在线程调用个awaitTermination时存放阻塞的线程。

  7. Work继承AQS和Runnable接口,是具体承载任务的对象,简单实现了不可重入锁,其中state=0为锁未被获取状态,state=1表示获取状态-1为默认。firstTask执行的第一个任务。

  8. DefaultThreadFactory是线程工厂,newThread 方法是对线程一个修饰。其中poolNumber是个静态原子变量,用来统计线程工厂个数。threadNumber统计线程工厂创建了多少线程。

  9. 源码分析

    1. public void execute(Runnable command)提交任务
      1. 当当前线程数个数小于corePoolSize,会向workers里面新增核心线程执行该任务
      2. 当大于或者等于corePoolSize放入任务队列(workQueue)中,如果当前线程池状态不是running的话就抛弃新任务
      3. 添加任务成功,则对线程进行第二次的状态校验,这是因为任务放入任务队列后,执行代码前任务可能已经变化,这里进行校验,如果是非running状态就从队列里面移除任务,并且执行拒接策略。如果二次校验通过,重新判断线程池里面是否有线程,如果没有新增一个线程。
      4. 如果任务失败,说明任务队列已满,尝试开始新的线程,如果当前线程个数>maximumPoolSize则执行拒绝策略。
    2. 添加任务
      1. 检查队列是否只在必要的时候为空(返回情况:stop,tidying,terminated;shutdown并且队列中到一个一个任务;shutdown并且队列为空)
      2. cas增加线程个数(超出最大线程数返回),成功返回,失败查看是否是状态改变是就返回,不是就重新cas
      3. 创建worker,使用mainLock实现wokers同步,
      4. 检查状态是否被shutdown了,是就返回不是添加任务,
      5. 成功启动任务。
    3. 工作线程worker的执行
      1. 获取任务,如果任务为null则执行清理工作,如果不为空,获取该任务的锁,执行相关任务,统计worker完成了多少任务,并且释放锁(加锁的目的是为了防止其他线程调用了shutdown,阻止当前任务的执行)
      2. 清理操作,统计完成任务数量,从工作集中删除当前任务,尝试设置为terminated状态。如果当前线程<核心个数增加。
    4. shutdown操作
      1. mainLock锁住
      2. 权限检查,调用的线程师傅有关闭的权限,没有抛出异常
      3. 设置为shutdown,是直接返回,不是设置为shutdown
      4. 设置中断标志、尝试设置为terminated,设置所有空闲线程中断标志。尝试获取worker自己的锁,成功则设置中断标志,目的是为了阻塞要从任务队列中获取任务的空闲队列。方法:使用cas 设置当前线程池的状态为tidying,设置成功就执行terminated,设置为terminated,激活所有因为调用条件变量await系列方法阻塞的所有线程。
      5. 解锁
    5. shutdownNow操作
      1. 不接受新的任务也不执行任务队列中的任务,正在执行的任务会立刻被中断,该方法会返回
    6. awaitTermination操作
      1. 当前线程不会被阻塞,知道线程状态变为terminated才返回,或则等待时间超时才返回。

java并发包中线程池ScheduledThreadPoolExecutor的原理研究

指定一个延迟时间后或者定时进行任务调度执行的线程池。ScheduledThreadPoolExecutor继承了ThreadPoolExecutor并实现了ScheduledExecutorService,线程池队列是DelayedWorkQueue。

  1. 介绍
    1. state 状态:ScheduledFutureTask是具有返回任务的继承自FutureTask。FutureTask内部有一个state用来表示任务状态
      1. 初始状态:new;执行中状态:completing : 执行中状态;normal:正常运行结束状态;exceptional:运行中异常;cancelled:任务取消;interrupting: 正在中断;interrupted:已经中断。
      2. 状态装换:new–>completing -->normal;new–>completing–>exceptional;new–>canceled;new–>interrupting–>interrupted
    2. period 任务类型:
      1. period=0:任务是一次性的
      2. period<0:任务是固定延迟时间可重复执行任务
      3. period>0:任务是固定频率的定时可重复执行任务
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

并发编程----4.java并发包中线程池的原理研究 的相关文章

  • 【Java线程】线程池的创建

    线程池装配类 线程池优雅停机控制 Configuration public class FeedBackExecutorConfig implements ApplicationListener
  • 常用线程池介绍

    线程池简介 1 线程池概念 线程池是首先创建一个线程 它们的集合成为线程池 使用线程池可以很好的提升性能 线程池在启动时即创建大量空闲的线程 程序将一个任务传给线程池 线程池就会启动一条线程来执行这个任务 执行线程完成后 该线程不会死亡 而
  • Java中synchronized同步锁用法及作用范围

    Java 中的 synchronized 关键字可以在多线程环境下用来作为线程安全的同步锁 本文主要对 synchronized 的作用 以及其有效范围进行讨论 Java中的对象锁和类锁 java的对象锁和类锁在锁的概念上基本上和内置锁是一
  • PyPy 安装

    目录 前言 1 下载 2 安装 2 1 安装包解压缩 2 2 添加路径至系统变量 3 cmd 调用 4 对比 Python 3 8的界面 总结 前言 提示 这里可以添加本文要记录的大概内容 听说 PyPy 的纯 Python 环境的运行速度
  • Java 线程池

    今天准备详细介绍java并发包下的Executor 以及Java提供了很多灵活的且极其方便的线程池的创建 嗯 那就慢慢说 大家肯定都学过Socket JavaSe的时候写聊天程序 游戏的服务器 以及Android程序自己需要提供服务器的 都
  • Java多线程导致CPU占用100%解决及线程池正确关闭方式

    文章目录 前言 一 cpu占用高排查问题 二 解决办法 使用AtomicLong 统计线程是否完成 再执行executor submit 提交新的任务导队列中 三 多线程关闭与令牌限流 前言 情景 1000万表数据导入内存数据库 按分页大小
  • Linux---多线程、线程池

    多线程 线程概念 线程就是进程中的一条执行流 负责代码的执行调度 在linux下线程执行流是通过pcb实现的 一个进程中可以有多个pcb 这些pcb共享进程中的大部分资源 所以线程被称为一个轻量级进程 Notes 进程是系统进行资源分配的基
  • 线程池的几种常见的创建的方式

    每次启动一个线程都要创建一个新的浪费资源的 还有时候线程过多的时候回造成服务器崩溃 所以有了线程池的诞生 线程池是用来管理线程的 下面是常用的几种创建线程的方式 一 创建大小不固定的线程池 这是一个线程类 public class Thre
  • php消息队列的应用

    欢迎加入 新群号码 99640845 最近打算开发一个新功能 计划应用消息队列 以前对消息队列都是简单的理论了解 真正应用之后把自己的感觉和一些理解整理下来 说正事分割线 具体的业务场景如下 用户下单 生成订单 支付 返回支付信息 就是正常
  • Semaphore 源码分析

    需要提前了解的知识点 AbstractQueuedSynchronizer 实现原理 类介绍 Semaphore 信号量 是用来控制同时访问特定资源的线程数量 它通过协调各个线程 以保证合理的使用公共资源 比如控制用户的访问量 同一时刻只允
  • JDK1.8 AbstractQueuedSynchronizer的实现分析(上)

    深度解析Java 8 JDK1 8 AbstractQueuedSynchronizer的实现分析 上 作者 刘锟洋 发布于 2014年7月31日 http www infoq com cn articles jdk1 8 abstract
  • 并发编程相关面试题(持续更新)

    1 juc包提供了哪些工具 用在什么场景 1 提供了比 synchronized 更加高级的各种同步结构 包括 CountDownLatch CyclicBarrier Semaphore 等 场景 可以实现更加丰富的多线程操作 比如利用
  • Android 中的线程池

    Android 中的线程池 线程池的优点 重用线程池中的线程 避免因为线程的创建和销毁所带来的性能开销 能有效控制线程池的最大并发数 避免大量的线程之间因互相抢占系统资源而导致的阻塞现象 能够对线程进行简单管理 并提供定时执行以及指定间隔循
  • Java多线程并行处理任务的实现

    Java多线程并行处理任务的实现 在实际项目开发的过程中 遇到过需要处理一个由多个子任务组成的任务的问题 顺序处理起来会造成响应时间超长 用户体验不好的问题 我想到一个解决方案 即使用多线程并行处理子任务 思路就是使用ThreadPoolE
  • java使用线程池批量插入mysql数据

    首先我们使用最原始的for循环插入数据 for int i 0 i lt 100000000 i service add new LongTest setStatus 1 setName NumberUtil getPwdRandom 5
  • 并发编程----4.java并发包中线程池的原理研究

    并发编程 4 java并发包中线程池的原理研究 java并发包中线程池ThreadPoolExecutor的原理研究 线程池的优点 线程的复用 减少线程创建和销毁带来的消耗 提供了一种资源限制和线程管理的手段 比如限制线程的个数和动态新增线
  • django高并发部署

    django高并发部署
  • 线程池的使用实例

    线程池的使用实例 number 创建线程个数 创建线程池 ExecutorService cachedThreadPool Executors newCachedThreadPool 每次线程执行完毕 计数 1 当计数减到 0 之后 才能解
  • 关于高并发与多线程中的线程池

    关于高并发与多线程中的线程池 定义 线程是稀缺资源 它的创建与销毁是一个相对偏重且耗资源的操作 而Java线程依赖于内核线程 创建线程需要进行操作系统状态切换 为避免资源过度消耗需要设法重用线程执行多个任务 线程池就是一个线程缓存 负责对线
  • 在一个线程池中,通常无法直接访问和检查单个线程的状态,因为线程池是由多个线程组成的,并且线程的执行情况可能会动态变化

    在一个线程池中 通常无法直接访问和检查单个线程的状态 因为线程池是由多个线程组成的 并且线程的执行情况可能会动态变化 然而 你可以通过一些方法来间接地查看线程是否在运行 一种常见的方法是为线程池中的每个线程设置一个标志或状态变量 用于表示线

随机推荐

  • 解决报错:Uncaught TypeError: Cannot read properties of undefined (reading ‘install‘)

    在做vue2项目时出现如下错误 页面空白且控制台出现如下错误 报错内容 Uncaught TypeError Cannot read properties of undefined reading install at Vue use vu
  • Anaconda + jupyter notebook + jupyter lab环境配置

    1 更换源 1 1 pip源 pip config set global index url https pypi tuna tsinghua edu cn simple pip config set install trusted hos
  • SQL SERVER2008存储过程加密与解密

    前言 我们在设置数据库存储过程时经常会用到加密 如果遇到版本更新需要修改存储过程时 如果设计数据库时的存储过程没有留存 所以就必须用到存储过程的解密了 原来自己有个解密存储过程在SQL2000下应用无问题 后来升级到SQL2008后不好用了
  • 4.网络爬虫—Post请求(实战演示)

    网络爬虫 Post请求实战演示 POST请求 GET请求 POST请求和GET请求的区别 获取二进制数据 爬 百度官网 https www baidu com logo实战 发送post请求 百度翻译实战 使用session发送请求 模拟登
  • 微信小程序部署到线上环境

    微信小程序部署到线上环境 一 微信小程序申请 申请 并认证 未认证不能发布 认证需要300元 目前只支持企业认证 详细见官网说明 https mp weixin qq com cgi bin registermidpage action i
  • mac os mysql忘记root密码_mac上mysql报错以及root密码忘记解决办法

    1 对于前者ERROR 2002 HY000 Can t connect to local MySQL server through socket tmp mysql sock 2 这个错误 一般是mysql服务没开 命令行下执行sudo
  • java8的时期和时间

    文章目录 旧版日期时间的问题 新版日期时间介绍 Java util date java sql date SimpleDateFormatter calendar java8日期 DateTimeFormatter 计算 java8之前 j
  • Python学习 第五章 图形界面设计

    第五章 图形界面设计 1 常用的 Python GUI 库 1 1 Tkinter 1 2 wxPython 1 3 创建GUI程序 2 创建Windows窗口 3 几何布局管理器 3 1 pack 包装 3 2 grid 网格 3 3 p
  • leetcode移动零c++

    给定一个数组 nums 编写一个函数将所有 0 移动到数组的末尾 同时保持非零元素的相对顺序 示例 输入 0 1 0 3 12 输出 1 3 12 0 0 说明 必须在原数组上操作 不能拷贝额外的数组 尽量减少操作次数 整体思路 题目中都出
  • 软件项目经理的基本职责

    软件项目经理的基本职责 1 制定项目计划 并根据各种变化修改项目计划2 实施 项目的管理 开发 质量保证过程 确保客户的成本 进度 绩效和质量目标 3 制定有效的项目决策过程4 确保在项目生命周期中遵循是实施公司的管理和质量政策5 选择一个
  • VC++ CComboBox自绘(选择下拉列表框)

    效果图 头文件定义 CSWCheckComboBox h pragma once class CSWCheckComboBox public CComboBox DECLARE DYNAMIC CSWCheckComboBox 成员私有结构
  • gdal解析tif

    bool HandleTif ReadTif tif文件读取 std string name D XX xx tif const char charName name c str 注册 GDALAllRegister 以防中文名不能正常读取
  • Docker本地镜像推送到私有库

    Docker Registry是官方提供的工具 可以用于构建私有镜像仓库 1 下载镜像Docker Registry docker pull registy 2 运行私有库Registry 相当于本地有个私有Docker hub docke
  • 计算机基础——Excel 2010

    天软备考交流群 365218976 1 Excel 2010的基本操作 1 1 Excel的窗口界面 1 2 工作簿与工作表 1 3 单元格区域的管理 1 4 工作表的管理 1 5 输入和编辑数据 1 6 行 列和单元格的管理 1 7 批注
  • java代码引用jar包中文件的方法

    jar是一个单独的文件 里面的文件称之为资源 有两种方法获取 里面的资源文件 一般将资源文件放到resources文件夹中 1 推荐 静态和非静态方法中都能用 ClassName class getClassLoader getResour
  • 刷脸支付服务商抓住机会迎头赶上

    科技改变未来并不是一句口号 就拿买东西来讲 以前人们都是一手交钱一手交货 拿到大额的纸币 还要验真假 而现在移动支付成为主要付款方式 只要一部手机 扫一扫就能付款 一开始也有很多人不习惯手机支付 因为觉得没有现金实在 整天就是一堆数字转来转
  • 前端手写(正则、字符串、函数)

    1 实现千位分隔符 保留三位小数 parseToMoney 1234 56 return 1 234 56 parseToMoney 123456789 return 123 456 789 parseToMoney 1087654 321
  • ajax 传回underfined,$.jquery ajax返回的数据(json)显示为’undefined’

    这里我有一个简单的 PHP脚本 它以json格式显示数据库中的一些值 source GET source query MysqL query SELECT FROM images WHERE big thumb source results
  • Anaconda安装教程及numpy环境配置

    一 下载Anaconda 下载地址 https www anaconda com 二 安装Anaconda 1 进入官网后 看不懂英文可以先将网页翻译成中文 然后点击产品 gt 个人版 如图进入下载页面 2 可以直接点击下载 也可以滚动到页
  • 并发编程----4.java并发包中线程池的原理研究

    并发编程 4 java并发包中线程池的原理研究 java并发包中线程池ThreadPoolExecutor的原理研究 线程池的优点 线程的复用 减少线程创建和销毁带来的消耗 提供了一种资源限制和线程管理的手段 比如限制线程的个数和动态新增线