1.1.1.多线程的发展--对cpu性能的压榨史

一.压榨历史

1.单进程人工切换。纸带机。只能解决简单的数学问题。

2.单道批处理。多进程批处理。多个任务批量执行。解决手动操作时需要人工切换作业导致的系统利用率低的问题

3.多进程并行处理。把程序写在不同的内存位置来回切换。当一个作业在等待I/O处理时,多批处理系统会通过相应调度算法调度另外一个作业让计算机执行

4.多线程。一个程序内部不同任务的来回切换。实现进程中任务的切换,又可以避免进程切换内存地址空间(将计算机实际调度的单元转到线程)。

5.纤程/协程与管程

二.相关含义介绍

什么是程序?什么是进程?什么是进程?什么是纤程/协程、管程?

1.程序-->抽象概念

操作系统可以执行的一个计算机文件。是一组计算机能识别和执行的指令序列。如QQ.exe

2.进程-->静态概念

进程是程序计算机(内存)中的一次运行活动。更通俗一点来说:进程是程序的实例化(类似于程序是class,进程是class的对象)。

进程是系统进行资源分配的基本单位,进程是线程的容器。

3.线程-->动态概念

一条线程指的是进程中一个单一顺序的执行路线(也可以说是执行流、控制流)。即进程中的实际运行单位。

资源调度的基本单位。

4.线程上下文

线程上下文是指某一时间点 CPU 寄存器和程序计数器的内容。

4.1.使用场景

上下文切换 (context switch) 。即任务切换, 或者CPU寄存器切换。

当多任务内核决定运行另外的任务时, 它保存正在运行任务的当前状态, 也就是CPU寄存器中的全部内容。这些内容被保存在任务自己的堆栈中, 入栈工作完成后就把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU寄存器, 并开始下一个任务的运行, 这一过程就是context switch。

4.2.上下文切换带来的问题

程序执行效率与线程并发数,从正相关变为负相关;

三.思考问题

1.单核的CPU设定多线程是否有意义?

其实个人的观点是,需要分析多线程的本质-->是对cpu性能的压榨。

那么,如果说单线程已经达到非常好的cpu利用率,则使用多线程意义不是太大。这种作业就称为cpu密集型(性能瓶颈是CPU运算)。

相对的,将性能瓶颈是IO(网络通信、硬盘读写、阻塞等待等)的作业称为io密集型。因为这种作业会造成cpu空闲,而使用多线程可显著减少此情况。

2.工作线程数是不是设置得越大越好?

a.先看一个示例:
package com.pavin.thread;
​
import java.text.DecimalFormat;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
​
public class multiThread_01 {
​private static double[] nums = new double[1_0000_0000];private static Random r = new Random();private static DecimalFormat df = new DecimalFormat("0.00");static {for (int j = 0; j < nums.length; j++) {nums[j] = r.nextDouble();}}
​private static void singleThread() {long start = System.currentTimeMillis();
​double result = 0.0;for (int j = 0; j < nums.length; j++) {result += nums[j];}
​long end = System.currentTimeMillis();System.out.println("1   " + " singleThread: cost " + (end-start) + "ms result: " + df.format(result));}
​static double result1 = 0.0, result2 = 0.0, result3 = 0.0;private static void twoThreads() throws InterruptedException {
​Thread t1 = new Thread(() -> {for (int j = 0; j < nums.length / 2; j++) {result1 += nums[j];}});
​Thread t2 = new Thread(() -> {for (int j = nums.length / 2; j < nums.length; j++) {result2 += nums[j];}});
​long start = System.currentTimeMillis();t1.start();t2.start();t1.join();t2.join();
​result3 = result1 + result2;long end = System.currentTimeMillis();System.out.println("2   " + " Threads: cost " + (end-start) + "ms result: " + df.format(result3));}
​private static void multiThreads(int threadCount) throws InterruptedException {
​Thread[] threads = new Thread[threadCount];double[] results = new double[threadCount];final int segmentCount = nums.length / threadCount;CountDownLatch latch = new CountDownLatch(threadCount);
​for (int i = 0; i < threadCount; i++) {int m = i;
​threads[i] = new Thread(() -> {for (int j = m * segmentCount; j < (m+1) * segmentCount && j < nums.length; j++) {results[m] += nums[j];}});
​latch.countDown();}
​double result = 0.0;long start = System.currentTimeMillis();for (Thread t : threads) {t.start();}
​latch.await();for (double v : results) {result += v;}
​long end = System.currentTimeMillis();System.out.println(threadCount + " Threads: cost " + (end-start) + "ms result: " + df.format(result));}
​public static void main(String[] args) throws InterruptedException {singleThread();twoThreads();
​multiThreads(10000);}
}

输出结果:

1    singleThread: cost 134ms result: 49997084.08
2    Threads: cost 78ms result: 49997084.08
10000 Threads: cost 1012ms result: 49997084.08

由此可见,使用两个线程时明显比一个线程更快,但是使用10000个线程时,非常慢。所以线程并不是越大越好。

b.造成效率下降的原因

见线程上下文

3.工作线程数(线程池中的线程数量)设置为多少合适?

公式+压测

a.公式

CPU密集型:理论上线程的数量=CPU核数最合适。

不过实际中一般会设为CPU核数+1。此时当线程因为偶尔的内存页失效或其他原因导致阻塞时,这个额外的线程可以顶上,从而保证CPU的利用率

IO密集型 :线程数 = CPU核心数 * 目标CPU利用率 *(1+平均等待时间/平均工作时间)

b.实际中的问题
i.环境开销

比如一个普通的SpringBoot 为基础的业务系统,默认Tomcat容器+HikariCP连接池+G1回收器。

Tomcat有自己的线程池,HikariCP也有自己的后台线程,JVM也有一些编译的线程,连G1都有自己的后台线程。这些线程也是运行在当前进程、当前主机上的,也会占用CPU的资源。

ii.测算"平均等待时间"、“平均工作时间”

方法1,通过日志和统计的方式得出。

方法2,第三方工具:profiler/Jprofiler

c.实际策略

一般情况下,内部业务系统相对于性能,更注重稳定好用、符合需求。实际生产推荐的线程数:CPU核心数+1

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

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

相关文章

C语言-函数STRCPY

strcpy char *strcpy(char *restrict dst, const char *restrict src);把src的字符串拷贝到dst restrict表明src和dst不重叠&#xff08;C99&#xff09; 返回dst 为了能链起代码来 复制一个字符串 char dst (char)malloc(strlen(src) 1); strcpy(dst, src);

从单向链表中删除指定值的节点

输入一个单向链表和一个节点的值&#xff0c;从单向链表中删除等于该值的节点&#xff0c;删除后如果链表中无节点则返回空指针。 链表的值不能重复。构造过程&#xff0c;例如输入一行数据为:6 2 1 2 3 2 5 1 4 5 7 2 2则第一个参数6表示输入总共6个节点&#xff0c;第二个参数…

通过仿真理解完整的阵列信号噪声模型

概要 噪声对无线电设备的信号接收会造成影响,是通信、雷达、导航、遥感等工程应用领域中的关键考虑因素。通常认为阵列合成能够提升信噪比,但忽略了这一论断的前提,即不同通道引入的噪声互不相关。但实际应用中,接收的噪声不仅仅包含信道引入的不相关噪声,还包含从外界环…

1-6、编程语言排行榜

语雀原文链接 https://www.tiobe.com/tiobe-index/

IntelliJ IDEA创建一个Maven项目

在IDEA中创建Maven项目&#xff0c;前提是已经安装配置好Maven环境 。 本文主要使用的是IntelliJ IDEA 2022.2.1 (Community Edition) 1.创建一个新project:File>Project 2.修改Maven配置&#xff1a;File>Settings>搜索maven 创建好的工程如下&#xff1a; src/main…

使用NanoPi NEO4进行rtsp拉流

使用系统&#xff1a;FriendlyDesktop系统 使用python进行编程&#xff0c;分别使用opencv与ffmpeg进行功能实现&#xff0c;折腾了挺长时间&#xff0c;代码很简单&#xff0c;主要是环境搭建。主要是python、opencv-python、ffmpeg-python、numpy之间的版本兼容&#xff0c;…

Chart 8 内核优化

文章目录 前言8.1 内核融合和拆分8.2 编译选项8.3 Conformant&#xff08;规范&#xff09; vs. fast vs. native math functions8.4 Loop unrolling8.5 避免分支发散8.6 Handle image boundaries8.7 Avoid the use of size_t8.8 通用 vs. 具名内存地址空间8.9 Subgroup8.10 Us…

七个常用<python装饰器>---足够改进代码质量 (保姆详解)

前言: 写代码嘛&#xff0c;关键是得让它既好用又好看&#xff0c;这不&#xff0c;Python装饰器就摆在那儿。咱们程序员有时也得有那么点艺术家的腔调&#xff1a;讲求效率&#xff0c;追求代码的简洁优雅&#xff0c;偶尔还得装装X&#xff0c;不是吗&#xff1f; 翻开人家…

SpringSecurity6 | 自定义认证规则

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…

移相干涉技术1-多种干涉条纹仿真模拟生成(原理转载+代码实现 包括模拟生成干涉条纹图)

过去的干涉测量技术是通过人的肉眼或者相机拍摄&#xff0c;来直观判断干涉图中条纹特征进而完成测量&#xff0c;该方法的不稳定因素&#xff08;比如人的主观意志&#xff09;很多&#xff0c;其精度误差在/10左右38]&#xff1b;现代干涉测量技术通过将电子技术、计算机技术…

智能优化算法应用:基于厨师算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于厨师算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于厨师算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.厨师算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

代码随想录-刷题第二十一天

530.二叉搜索树的最小绝对差 题目链接&#xff1a;530. 二叉搜索树的最小绝对差 思路&#xff1a;二叉搜索树的中序遍历是有序的。根据二叉搜索树的这个特性来解题。 class Solution {// 同样利用二叉树中序遍历是一个有序数组。private List<Integer> list new Arra…

一加 12 Pop-up快闪活动来袭,十城联动火爆开启

12 月 9 日&#xff0c;一加 12 Pop-up 快闪活动在北京、深圳、上海、广州等十城联动开启&#xff0c;各地加油欢聚快闪现场&#xff0c;抢先体验与购买一加 12。作为一加十年超越之作&#xff0c;一加 12 全球首发拥有医疗级护眼方案和行业第一 4500nit 峰值亮度的 2K 东方屏、…

C++新经典模板与泛型编程:策略类模板

策略类模板 在前面的博文中&#xff0c;策略类SumPolicy和MinPolicy都是普通的类&#xff0c;其中包含的是一个静态成员函数模板algorithm()&#xff0c;该函数模板包含两个类型模板参数。其实&#xff0c;也可以把SumPolicy和MinPolicy类写成类模板—直接把algorithm()中的两…

【Linux】无法使用 ifconfig 查看系统网络接口信息,报错 command not found: ifconfig

问题描述 ifconfig是一个用于配置和显示系统网络接口信息的命令行工具。它通常用于Unix、Linux和其他类Unix系统中。 通过ifconfig命令&#xff0c;你可以查看和修改系统中网络接口的配置信息&#xff0c;包括IP地址、子网掩码、MAC地址、MTU&#xff08;最大传输单元&#x…

javacv踩坑记录

前一阵学习opencv&#xff0c;发现在做人脸识别的时候遇到一些类库不存在的情况&#xff0c;查找后发现是由于拓展包没有安装完全&#xff08;仅安装了基础版&#xff09;。由于网络的问题&#xff08;初步猜测&#xff09;&#xff0c;始终无法安装好拓展包。 于是另辟蹊径&am…

MongoDb数据库

一、命令交互 1.1 数据库命令 1.显示所有数据库&#xff1a; show dbs 2.切换到指定数据库&#xff0c;如果没有则自动创建数据库 use databaseName 3.显示当前所在数据库 db 4.删除当前数据库 use 库名 db.dropDatabase() 1.2 集合命令 1.创建集合 db.createColl…

[文档级关系抽取|ACL论文]文档级关系抽取中语言理解的基础模型

Did the Models Understand Documents? Benchmarking Models for Language Understanding in Document-Level Relation Extraction School of Computer Science, Fudan University | ACL 2023.06 | 原文链接 Background 过去的工作大多数都是从单个句子中收获更多的关系&am…

MongoDB中的$type操作符和limit与skip方法

本文主要介绍MongoDB中的$type操作符和limit与skip方法。 目录 MongoDB的$type操作符MongoDB的limit方法MongoDB的skip方法 MongoDB的$type操作符 MongoDB中的$type操作符用于检查一个字段的类型是否与指定的类型相匹配。它可以用于查询和投影操作。 $type操作符可以与以下数…

php,redis实现一个电影热度排行榜

要实现电影热度排行榜&#xff0c;需要记录每个电影的热度值&#xff0c;热度值可以根据不同的算法计算&#xff0c;例如&#xff1a;观看次数、评分数、评论数等。这里我们以观看次数为例。 首先&#xff0c;需要使用 Redis 的 Sorted Set 数据结构来存储电影的热度值和电影 …