CPU密集型和IO密集型任务的权衡:如何找到最佳平衡点

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

目录

  • 一、导读
  • 二、概览
  • 三、CPU密集型与IO密集型
    • 3.1、CPU密集型
    • 3.2、I/O密集型
  • 四、如何区分IO密集型、CPU密集型任务
  • 五、 推荐阅读

一、导读

我们继续总结学习Java基础知识,温故知新。

二、概览

CPU密集型与I/O密集型是在计算机上执行任务的两种策略,在并发执行任务场景下,我们需要选择使用多线程或多进程;
如果是IO密集型任务,使用多线程,线程越多越好;
如果是CPU密集型任务,使用多进程,线程数量与CPU核心数匹配。

我们了解这些概念有助于在资源分配和性能优化等方面有很大的帮助。
我们在选择线程池的时候,我们需要知道某一个任务是否是CPU消耗型的任务,还是说IO类型的任务,以便充分的调用CPU资源。

三、CPU密集型与IO密集型

3.1、CPU密集型

CPU密集型,也叫计算密集型
系统运行时,CPU读写I/O(硬盘/内存)时可以在很短的时间内完成,几乎没有阻塞时间(等待I/O的实时间),而CPU一直有大量运算要处理,因此CPU负载长期过高。

CPU密集几乎无I/O阻塞,CPU一直会全速运行。如果是单核情况下,开多线程是没有意义的,一个CPU来回切着运行,增加线程切换的资源消耗。
可见,CPU密集任务只有在多核CPU上、开多线程才可能提速。

CPU使用率较高时(如我们训练算法模型、搞训练集),通常线程数只需要设置为CPU核心数的线程个数就可以了。

一般其计算公式可遵循:CPU密集型核心线程数 = CPU核数 + 1。

《Java并发编程实践》这么说:

计算密集型的线程恰好在某时因为发生一个页错误或者因其他原因而暂停,刚好有一个“额外”的线程,可以确保在这种情况下CPU周期不会中断工作。

特点:

  • 进行大量的计算
  • 消耗CPU资源,较高的CPU占用率,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。
  • 较少的IO操作

3.2、I/O密集型

I/O密集型相反,听名字就知道,系统运行多是CPU在等I/O (硬盘/内存) 的读写操作,此类情景下CPU负载并不高。

I/O密集型的程序一般在达到性能极限时,CPU占用率仍然较低。
这可能是因为任务本身需要大量I/O操作,没有充分利用CPU能力,导致线程空余时间很多。
通常我们会开CPU核心数数倍的线程,在线程进行 I/O 操作 CPU 空闲时,启用其他线程继续使用 CPU,以提高 CPU 的使用率,充分利用CPU资源。

一般其计算公式可遵循:I/O密集型核心线程数 = (线程等待时间/ 线程CPU时间 + 1)* CPU数目。

当然我们也看到有多种计算公式,但都不是最优解,具体情况需结合项目实际使用,配置合适的线程数

一般来说:文件读写、DB读写、网络请求等都是I/O密集型

特点:

  • 高IO操作
  • 计算操作少
  • CPU占用率低

四、如何区分IO密集型、CPU密集型任务

我们需要知道某一个任务是否是CPU消耗型的任务(定容线程池),还是说IO类型的任务(缓存线程池),充分的调用CPU资源。

那在此之前,我们需要知道两个概念:

Wall Duration:代码执行时间(包括了running + runnable + sleep等所有时长)

比如我们要知道某方法执行时间,可以通过系统时间差即可:

    void method() {
        long start = System.currentTimeMillis();
        // 业务代码    
        long wallTime = System.currentTimeMillis() - start;
    }

CPU Duration: 代码消耗CUP的时间(重点指标,优化方向)。

    void method() {
        long start = SystemClock.currentThreadTimeMillis(); //当前线程运行了多少时间(毫秒值,不含thread或systemclock.sleep的值)
        // 业务代码    
        long wallTime = SystemClock.currentThreadTimeMillis() - start;
    }

那如果在Android 端,我们借助SysTrace工具即可(具体方法可自行搜索),如下图
1
通过SysTrace查看 Wall Duration 与 CPU Duration,

消耗的CPU时间片较多,我们就把它定义为CPU消耗型的任务,放在定容线程池里调度(即线程数量固定)

消耗的时间片少,我们就把它定义为IO类型的任务,放在缓存线程池中。

  • 缓存线程池(CachedThreadPool)是Java中的一种线程池类型。它是一种动态线程池,可以根据需要自动创建新的线程,并在线程空闲一段时间后销毁。

以上是比较粗暴的分类方法,如果是混合型的任务,那就要慢慢调试,找个最佳数量。

五、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【字符流】案例:集合到文件

案例:集合到文件 1.需求: 把ArrayList集合中的字符串数据写入到文本文件。要求:每一个字符串元素作为文件中的一行数据 2.思路 创建ArrayList集合往集合中存储字符串元素创建字符缓冲输出流对象遍历集合,得到每一个字符串数据调…

SpringBoot中间件—ORM(Mybatis)框架实现

目录 定义 需求背景 方案设计 代码展示 UML图 实现细节 测试验证 总结 源码地址(已开源):https://gitee.com/sizhaohe/mini-mybatis.git 跟着源码及下述UML图来理解上手会更快,拒绝浮躁,沉下心来搞 定义&#x…

界面控件DevExpress WPF数据编辑器组件,让数据处理更灵活!(二)

界面控件DevExpress WPF编辑器库可以帮助用户提供直观的用户体验,具有无与伦比的运行时选项和灵活性。WPF数据编辑器提供了全面的掩码和数据验证支持,可以独立使用,也可以作为容器控件(如DevExpress WPF Grid和WPF TreeList)中的单元格编辑器…

【pytho】request五种种请求处理为空和非空处理以及上传excel,上传图片处理

一、python中请求处理 request.args获取的是个字典,所以可以通过get方式获取请求参数和值 request.form获取的也是个字典,所以也可以通过get方式获取请求的form参数和值 request.data,使用过JavaScript,api调用方式进行掺入jso…

Cmake笔记记录

工作后开发内容都是在Linux系统下完成,cmake使用比较频繁,找到一篇很不错的CMake笔记。 记录下来方便自己查阅。 目录 1.CMake介绍2.示例一:编译单个文件CMAKE_BUILD_TYPE 3.示例二:编译同个目录下多个文件aux_source_directory()…

QT通过TCP协议发送结构体数据

文章目录 前言1. memcpy方式1.1 发送整个结构体1.2 发送部分数据 2. QDataStream2.1 符号<<2.2 wrieteRawData 总结 前言 做上位机的时候下发数据&#xff0c;数据是一个结构体&#xff0c;这里就阐述一下怎么通过TCP协议发送结构体。 我自己写的时候主要通过两种方式&a…

JavaWeb 速通HTTP

目录 一、HTTP快速入门 1.HTTP简介 : 2.HTTP请求头 : 3.HTTP响应头 : 二、HTTP响应状态码 1.基本介绍 : 2.常见状态码 : 3.状态码的分类 : 4.完整状态码汇总 : 三、HTTP请求包和响应包 1.请求包分析 : 1 GET请求 (1) 说明 (2) doGet返回数据给浏览器 (3) form表单提…

华为云CodeArts产品体验的心得体会及想法

文章目录 前言CodeArts 的产品优势一站式软件开发生产线研发安全Built-In华为多年研发实践能力及规范外溢高质高效敏捷交付 功能特性说明体验感受问题描述完结 前言 华为云作为一家全球领先的云计算服务提供商&#xff0c;致力于为企业和个人用户提供高效、安全、可靠的云服务。…

C++---树形DP---树的中心(每日一道算法2023.7.19)

注意事项&#xff1a; 本题为"树形DP—树的最长路径"的近似题&#xff0c;同时涉及到 单链表模拟邻接表存储图 的操作&#xff0c;建议先理解那篇文章。 题目&#xff1a; 给定一棵树&#xff0c;树中包含 n 个结点&#xff08;编号1~n&#xff09;和 n−1 条无向边…

uniapp查看ios打包后的Info.plist文件

最近在用 uni 开发 ios 的时候给项目添加了自定义的 Info.plist 文件&#xff0c;但是打包后发现并没有生效&#xff0c;才有了查看打包后的 Info.plist 文件想法。 HBuilderX3.6.5起&#xff0c;支持直接在应用项目中配置 iOS 平台的 Info.plist 和 资源文件&#xff08;Bundl…

C# List 详解二

目录 5.Clear() 6.Contains(T) 7.ConvertAll(Converter) ,toutput> 8.CopyTo(Int32, T[], Int32, Int32) 9.CopyTo(T[]) 10.CopyTo(T[], Int32) C# List 详解一 1.Add(T)&#xff0c;2.AddRange(IEnumerable)&#xff0c;3.AsReadOnly()&…

RabbitMQ集群搭建

说明&#xff1a;集群&#xff0c;不管是Redis集群&#xff0c;还是MQ集群&#xff0c;都是为了提高系统的可用性&#xff0c;使系统不至于因为Redis、MQ宕机而崩溃。本文介绍RabbitMQ集群搭建&#xff0c;RabbitMQ集群分为以下三类&#xff1a; 普通集群 镜像集群 仲裁队列 …

循环链表的实现

循环链表简介 简单来说&#xff0c;单链表像一个小巷&#xff0c;无论怎么样最终都能从一端走到另一端&#xff0c;循环链表则像一个有传送门的小巷&#xff0c;因为循环链表当你以为你走到结尾的时候&#xff0c;其实你又回到了开头。循环链表和非循环链表其实创建的过程以及…

程序员基础知识—IP地址

文章目录 一、什么是IP地址二、IP地址的分类三、子网掩码 一、什么是IP地址 IP地址就像我们需要打电话时的电话号码一样&#xff0c;它用来标识网络中的一台主机&#xff0c;每台主机至少有一个IP地址&#xff0c;而且这个IP地址是全网唯一的。IP地址由网路号和主机号两部分组…

Elasticsearch/Enterprise Search/Kibana安装记录

目录 Elasticsearch的安装导入 elasticsearch PGP密钥 安装使用APT安装手动下载安装 启动elasticsearch安全功能重新配置节点以加入现有集群启用系统索引的自动创建功能运行Elasticsearch(在systemd下)检查Elasticsearch是否正在运行Elasticsearch配置外网访问 第三方包安装ela…

Python学习(十六)柱状图

zdaPython学习&#xff08;十四&#xff09;折线图开发_yikuaidabin的博客-CSDN博客 案例数据资源 ↑ """演示基础柱状图的开发 """ from pyecharts.charts import Bar from pyecharts.options import LabelOpts # 使用Bar构建基础柱状图 bar …

【网络】socket——TCP网络通信 | 日志功能 | 守护进程

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 上篇文章中本喵介绍了UDP网络通信的socket代码&#xff0c;今天介绍TCP网络通信的socket代码。 TCP &a…

深度理解 Spring AOP

一、什么是AOP(面向切面编程)&#xff1f;&#x1f349; AOP 为 Aspect Oriented Programming 的缩写&#xff0c;意思为面向切面编程&#xff0c;是通过预编译方式 和运行期 动态代理 实现程序功能的统一维护的一种技术。 AOP &#xff08;面向切面编程&#xff09;是 OOP&a…

深度理解 Spring IOC

Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息&#xff0c;并在Spring容器中生成一份相应的Bean配置注册表&#xff0c;然后根据这张注册表实例化Bean&#xff0c;装配好Bean之间的依赖关系&#xff0c;为上层应用提供准备就绪的运行环境。 Bean缓存池&…

OJ练习第143题——二叉树展开为链表

二叉树展开为链表 力扣链接&#xff1a;114. 二叉树展开为链表 题目描述 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终…