深入理解CPU密集型与IO密集型任务、线程池如何选择?

news/2024/5/20 10:05:21 标签: 面试, 职场和发展, java, juc, 并发, 线程池

目录

1、理解什么是CPU密集型与IO密集型

1.1 CPU密集型

概念解释

策略

1.2 I/O密集型

概念解释

策略

2、《Java并发编程实践》:具体的线程数该如何设置?线程池参数如何设置?

 参数解释

3、总结


1、理解什么是CPU密集型与IO密集型

1.1 CPU密集型

概念解释

        即,计算密集型,I/O能够在很短的时间内完成,而相对的CPU却有大量运算要处理。例如计算大量的加减乘除、矩阵运算等,都属于CPU密集型。

策略

        我们知道,线程是最小的可执行单位
        严格来说,每个核心同一时间只能处理一条线程的指令,因此如果是单核CPU的情况下,创建再多的线程其实也不会加快运算速度,反而会因为单核的线程并发导致线程上下文的切换而降低效率。(类似于一个工人干了多个活)
        而在多核cpu下,可以创建多个线程让多个cpu并行运算,一起工作。(多个工人同时做多个活),从而提升效率。

1.2 I/O密集型

        IO密集型指的是系统的CPU性能相对硬盘、内存要好很多,此时,大部分的状况是CPU在等I/O (硬盘/内存) 的读/写操作,但CPU的使用率不高。
        在实际开发中,IO密集型任务也很常见,例如:
        磁盘IO:读写本地的数据库、Redis,等。

        网络IO:http 请求、远程数据库读写、远程 Redis 读写,等

概念解释

        这里需要解释一下,什么叫“CPU在等I/O (硬盘/内存) 的读/写操作”?

        在传统的阻塞式 I/O 操作模型中,当 CPU 发起一个 I/O 请求后,发起该操作的线程会一直阻塞等待 I/O 操作的完成:
        当线程发起一个阻塞式的 IO 操作时,它会等待操作完成,期间线程将被挂起,无法继续执行其他指令,这种模型导致了CPU的使用率不高。需要注意的是,IO 阻塞并不是直接阻塞 CPU 的执行,而是阻塞了发起 IO 操作的线程。其他未受影响的线程仍然可以继续执行。

策略

        在上面的基础上我们知道,在处理IO密集型任务,即使创建了线程,也可能因为IO的阻塞等待而让线程阻塞、从而导致CPU不干活一直摸鱼🐟🐟
        为了不让cpu偷偷休息,可以增加更多的线程,当一个线程或进程在等待某个 I/O 操作完成时,其他线程或进程可以继续执行其他任务,减少了 CPU 空闲时间,这是可以通过线程池实现的复用技术。

2、《Java并发编程实践》:具体的线程数该如何设置?线程池参数如何设置?

结论:Ncpu 表示 核心数,线程数设置规则如下

如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 Ncpu+1

如果是IO密集型任务,参考值可以设置为 2 * Ncpu

 参数解释

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

        对于IO密集型,假设所有线程都被阻塞,有Ncp个空闲CPU,因此可以再多给一样数量的线程数,因此为2倍Ncpu

实际上,有这样的计算公式:

最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目

3、总结

        实际上,CPU密集型如果卡顿,往往是因为cpu不够用;IO密集型卡顿往往是因为线程不够用。 

 


http://www.niftyadmin.cn/n/4959603.html

相关文章

MySQL 存储函数

文章目录 1.简介2.创建存储函数3.调用存储函数4.查看存储函数5.修改存储函数6.删除存储函数参考文献 1.简介 MySQL 存储函数(Stored Function)和存储过程类似,也是存储在数据库中的程序,但是它会返回一个计算结果。 存储函数可以…

如何在Java实现TCP方式发送和接收Socket消息(多线程模式)

目录 导言:正文:1. 创建Server端:2. 创建Client端:3. 多线程模式: 代码示例Server端代码示例:Client端代码示例:同步模式发送TCP消息异步模式 结论: 导言: 在Java编程中…

2.vue3+ts+element-plus后台管理界面布局及动态侧边栏实现

1. 界面布局 利用element-plus的布局组件实现&#xff1a; <el-container> 整个布局容器&#xff0c; <el-header> 顶部布局容器&#xff0c; <el-aside> 侧边布局容器 <el-main> 主要布局容器。 采用组件化思想&#xff0c;将header和aside组件化…

使用Kind搭建本地k8s集群环境

目录 1.前提条件 2.安装Kind 3.使用Kind创建一个K8s集群 3.1.创建一个双节点集群&#xff08;一个Master节点&#xff0c;一个Worker节点&#xff09; 3.2.验证一下新创建的集群信息 3.3.删除刚刚新建的集群 4.安装集群客户端 4.1.安装kubectl 4.1.1.验证kubectl 4.2.安…

【数据结构】实现带头双向循环链表

目录 前言&#xff1a;一、介绍带头双向循环链表1.带头双向循环链表的结构2.带头双向循环链表的功能 二、实现带头双向循环链表1.创建节点的结构2.函数的声明2.函数的实现&#xff08;1&#xff09;创建一个新节点&#xff08;2&#xff09;初始化哨兵位&#xff08;带头&#…

第十七章、【Linux】认识系统服务

17.1 什么是daemon与服务&#xff08;service&#xff09; 系统为了某些功能必须要提供一些服务 &#xff08;不论是系统本身还是网络方面&#xff09;&#xff0c;这个服务就称为 service 。 但是 service 的提供总是需要程序的运行吧&#xff01;否则如何执行呢&#xff1f;…

ResourceBundle类:读取配置文件

ResourceBundle类是java自带的类&#xff0c;类路径&#xff1a;java.util.ResourceBundle&#xff0c;用来读取项目中后缀为properties的配置文件。 下面简单举例说明一下用法&#xff1a; 数据准备 1&#xff09;配置文件名称&#xff1a;application.properties&#xff…

KDAB QML学习笔记Day3(5,6,7,8)

KDAB QML学习笔记Day3&#xff08;5,6,7,8&#xff09; 学习视频链接&#xff1a;Introduction to Qt / QML - all videos so far - YouTube B站链接&#xff1a;Introduction to Qt / QML_哔哩哔哩_bilibili Part05&#xff0c;06 示例代码 import QtQuick 2.15 import Q…