【操作系统】聊聊CPU上下文切换实操
如何查看系统的上下文切换情况
上一篇文章我们说了过多的上下文切换,会把CPU时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,那么当出现系统的上下文切换过多的时候,我们如果通过监控指标查看呢。
vmstat 是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常用来分析 CPU 上下文切换和中断的次数。
vmstat 5 代表的是5S输出一组
root@qxlxi:/data# vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----r b swpd free buff cache si so bi bo in cs us sy id wa st0 0 1296640 195580 158788 2402740 0 1 3 23 22 46 0 0 99 0 00 0 1296640 222836 158788 2402740 0 0 0 17 52 92 1 1 99 0 0
- cs(context switch)每秒上下文切换次数
- in (interrupt) 每秒中断的次数
- r (Running or Runnable) 是就绪队列的长度,也就是可运行的进程数(进行和等待)
- b (Blocked) 处于不可中断睡眠状态的进程数
从图中可以看到cs是92次上下文切换 in 52次中断。就绪队列和不可中断进程数都是0
查看每个进程的数据,使用 pidstat -w
root@qxlxi:/data# pidstat -w 5
Linux 5.4.0-100-generic (qxlxi) 09/23/2023 _aarch64_ (2 CPU)12:45:26 PM UID PID cswch/s nvcswch/s Command
12:45:31 PM 0 9 0.20 0.00 ksoftirqd/0
12:45:31 PM 0 10 3.79 0.00 rcu_sched
12:45:31 PM 0 11 0.20 0.00 migration/0
12:45:31 PM 0 17 0.20 0.00 migration/1
12:45:31 PM 0 18 0.40 0.00 ksoftirqd/1
12:45:31 PM 0 365 0.80 0.00 kworker/0:1H-kblockd
12:45:31 PM 0 382 0.20 0.00 kworker/1:1H-kblockd
12:45:31 PM 118 876 1.80 0.00 avahi-daemon
12:45:31 PM 0 885 0.20 0.00 irqbalance
12:45:31 PM 128 1490 0.20 0.00 gsd-color
12:45:31 PM 1000 1615 2.00 0.00 systemd
12:45:31 PM 1000 1708 0.20 0.00 Xorg
12:45:31 PM 1000 1888 0.20 0.00 gnome-shell
12:45:31 PM 1000 2006 0.20 0.00 gsd-color
12:45:31 PM 0 19788 0.20 0.00 systemd-journal
12:45:31 PM 0 60439 1.00 0.00 multipathd
12:45:31 PM 0 88948 4.19 1.60 systemd-udevd
12:45:31 PM 1000 115630 0.20 0.00 gnome-control-c
12:45:31 PM 0 487397 2.00 0.00 kworker/u4:1-events_power_efficient
12:45:31 PM 0 488871 6.99 0.00 kworker/1:1-events
12:45:31 PM 0 489061 0.40 0.00 kworker/u4:0-events_freezable_power_
12:45:31 PM 0 489366 8.18 0.00 kworker/0:2-events
12:45:31 PM 0 489376 0.20 0.00 pidstat
- cswch/s : 每秒自愿上下文切换(voluntary context switches)的次数
- nvcswch/s:每秒非自愿上下文切换 (non voluntary context switches) 的次数
自愿上下文切换:进程获取不到自愿的时候,发生的上下文切换,比如IO、网络、内存资源不足的时候。
非自愿上下文切换:进程执行时间到了,被系统强制调度,进而发生上下文切换,比如大量进程竞争CPU
场景分析
sysbench --threads=10 --max-time=300 threads run
模拟10个线程执行。
查看总体
root@qxlxi:/data# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----r b swpd free buff cache si so bi bo in cs us sy id wa st6 0 1296640 222000 158804 2403064 0 1 3 23 23 21 0 0 99 0 0
10 0 1296640 222000 158804 2403064 0 0 0 80 132863 2924643 15 80 5 0 05 0 1296640 222000 158804 2403064 0 0 0 0 142952 2734656 14 81 5 0 08 0 1296640 222000 158804 2403064 0 0 0 0 157159 2996906 14 85 1 0 07 0 1296640 221968 158804 2403064 0 0 0 0 140886 2726608 13 78 9 0 09 0 1296640 221968 158804 2403064 0 0 0 0 142394 2722918 14 80 6 0 0
查看上下文切换次数升级到200多万,而就绪队列达到了10,us和sy的和达到了100%,sy的占用率80多,肯定有大量的CPU竞争。重点的次数也达到了1W多。
综合分析,就绪队列过长,导致的大量进程上下文切换,从而导致系统CPU占用率更高。
查看进程
pidstat -w -u 1 查看进程上下文切换数据
qxlxi@qxlxi:~$ pidstat -w -u 1
Linux 5.4.0-100-generic (qxlxi) 09/23/2023 _aarch64_ (2 CPU)12:51:09 PM UID PID %usr %system %guest %wait %CPU CPU Command
12:51:10 PM 1000 1699 0.98 0.00 0.00 0.00 0.98 0 gvfs-afc-volume
12:51:10 PM 0 489611 28.43 160.78 0.00 0.00 189.22 0 sysbench
12:51:10 PM 1000 489646 0.00 0.98 0.00 0.00 0.98 1 pidstat12:51:09 PM UID PID cswch/s nvcswch/s Command
12:51:10 PM 0 10 2.94 0.00 rcu_sched
12:51:10 PM 0 18 0.98 0.00 ksoftirqd/1
12:51:10 PM 0 382 0.98 0.00 kworker/1:1H-kblockd
12:51:10 PM 1000 1615 1.96 0.00 systemd
12:51:10 PM 0 60439 0.98 0.00 multipathd
12:51:10 PM 0 487195 6.86 0.00 kworker/0:1-events
12:51:10 PM 0 488871 5.88 0.00 kworker/1:1-events
12:51:10 PM 0 489585 0.98 0.00 kworker/u4:2-events_freezable_power_
12:51:10 PM 1000 489646 0.98 53.92 pidstat12:51:10 PM UID PID %usr %system %guest %wait %CPU CPU Command
12:51:11 PM 128 1420 1.00 0.00 0.00 0.00 1.00 0 gnome-shell
12:51:11 PM 0 489611 26.00 161.00 0.00 0.00 187.00 0 sysbench12:51:10 PM UID PID cswch/s nvcswch/s Command
12:51:11 PM 0 10 8.00 0.00 rcu_sched
12:51:11 PM 0 18 3.00 0.00 ksoftirqd/1
12:51:11 PM 128 1420 3.00 12.00 gnome-shell
12:51:11 PM 1000 1615 2.00 0.00 systemd
12:51:11 PM 1000 1888 3.00 8.00 gnome-shell
12:51:11 PM 0 60439 1.00 0.00 multipathd
12:51:11 PM 0 487195 7.00 0.00 kworker/0:1-events
12:51:11 PM 0 487397 47.00 0.00 kworker/u4:1-events_unbound
12:51:11 PM 1000 488358 10.00 0.00 sshd
12:51:11 PM 0 488871 4.00 0.00 kworker/1:1-events
12:51:11 PM 0 489585 206.00 0.00 kworker/u4:2-events_unbound
12:51:11 PM 1000 489646 1.00 253.00 pidstat12:51:11 PM UID PID %usr %system %guest %wait %CPU CPU Command
12:51:12 PM 0 489611 19.00 169.00 0.00 0.00 188.00 0 sysbench
12:51:12 PM 1000 489646 0.00 1.00 0.00 1.00 1.00 1 pidstat12:51:11 PM UID PID cswch/s nvcswch/s Command
12:51:12 PM 0 10 4.00 0.00 rcu_sched
12:51:12 PM 0 18 10.00 0.00 ksoftirqd/1
12:51:12 PM 1000 1615 2.00 0.00 systemd
12:51:12 PM 1000 2130 1.00 0.00 evolution-alarm
12:51:12 PM 0 60439 1.00 0.00 multipathd
12:51:12 PM 0 487195 4.00 0.00 kworker/0:1-events
12:51:12 PM 0 487397 165.00 0.00 kworker/u4:1-events_unbound
12:51:12 PM 1000 488358 18.00 0.00 sshd
12:51:12 PM 0 488871 5.00 0.00 kworker/1:1-events
12:51:12 PM 0 489585 113.00 0.00 kworker/u4:2-events_freezable_power_
12:51:12 PM 1000 489646 1.00 289.00 pidstat12:51:12 PM UID PID %usr %system %guest %wait %CPU CPU Command
12:51:13 PM 0 489611 27.00 158.00 0.00 0.00 185.00 0 sysbench12:51:12 PM UID PID cswch/s nvcswch/s Command
12:51:13 PM 0 10 5.00 0.00 rcu_sched
12:51:13 PM 0 11 1.00 0.00 migration/0
12:51:13 PM 0 17 1.00 0.00 migration/1
12:51:13 PM 0 18 1.00 0.00 ksoftirqd/1
12:51:13 PM 1000 1615 2.00 0.00 systemd
12:51:13 PM 0 60439 1.00 0.00 multipathd
12:51:13 PM 0 487195 8.00 0.00 kworker/0:1-events
12:51:13 PM 0 487397 96.00 0.00 kworker/u4:1-flush-253:0
12:51:13 PM 1000 488358 15.00 0.00 sshd
12:51:13 PM 0 488871 5.00 0.00 kworker/1:1-events
12:51:13 PM 0 489585 165.00 0.00 kworker/u4:2-events_unbound
12:51:13 PM 1000 489646 1.00 258.00 pidstat
从图中可以发现,切换较多的自愿上下文切换是进程 kworker/u4:2-events_unbound,而这里只是显示的是进程的上下文切换,而CPU在运行的是时候, Linux 调度的基本单位实际上是线程
pidstat -wt 1 可以查看线程的指标1:06:41 PM UID TGID TID cswch/s nvcswch/s Command
01:06:43 PM 0 1 - 0.92 0.00 systemd
01:06:43 PM 0 - 1 0.92 0.00 |__systemd
01:06:43 PM 0 10 - 19.27 0.00 rcu_sched
01:06:43 PM 0 - 10 19.27 0.00 |__rcu_sched
01:06:43 PM 0 18 - 8.26 0.00 ksoftirqd/1
01:06:43 PM 0 - 18 8.26 0.00 |__ksoftirqd/1
01:06:43 PM 0 382 - 0.92 0.00 kworker/1:1H-kblockd
01:06:43 PM 0 - 382 0.92 0.00 |__kworker/1:1H-kblockd
01:06:43 PM 0 - 937 0.92 0.00 |__gmain
01:06:43 PM 128 - 1300 0.92 0.00 |__gvfs-afc-volume
01:06:43 PM 128 - 1422 0.92 0.00 |__gmain
01:06:43 PM 1000 1615 - 1.83 0.00 systemd
01:06:43 PM 1000 - 1615 1.83 0.00 |__systemd
01:06:43 PM 1000 - 1700 0.92 0.00 |__gvfs-afc-volume
01:06:43 PM 1000 1708 - 3.67 0.00 Xorg
01:06:43 PM 1000 - 1708 3.67 0.00 |__Xorg
01:06:43 PM 1000 1888 - 2.75 0.00 gnome-shell
01:06:43 PM 1000 - 1888 2.75 0.00 |__gnome-shell
01:06:43 PM 1000 - 1900 0.92 0.00 |__gmain
01:06:43 PM 1000 - 2336 0.92 0.00 |__gmain
01:06:43 PM 1000 - 2745 0.92 0.00 |__gmain
01:06:43 PM 0 - 56981 0.92 0.00 |__gmain
01:06:43 PM 0 60439 - 0.92 0.00 multipathd
01:06:43 PM 0 - 60439 0.92 0.00 |__multipathd
01:06:43 PM 0 - 60443 0.92 0.00 |__multipathd
01:06:43 PM 0 487397 - 0.92 0.00 kworker/u4:1-events_freezable_power_
01:06:43 PM 0 - 487397 0.92 0.00 |__kworker/u4:1-events_freezable_power_
01:06:43 PM 1000 489904 - 1.83 0.00 baobab
01:06:43 PM 1000 - 489904 1.83 0.00 |__baobab
01:06:43 PM 0 490271 - 7.34 0.00 kworker/0:2-events
01:06:43 PM 0 - 490271 7.34 0.00 |__kworker/0:2-events
01:06:43 PM 0 490366 - 3.67 0.00 kworker/1:3-events
01:06:43 PM 0 - 490366 3.67 0.00 |__kworker/1:3-events
01:06:43 PM 0 - 490582 37280.73 249111.93 |__sysbench
01:06:43 PM 0 - 490583 30613.76 227590.83 |__sysbench
01:06:43 PM 0 - 490584 42267.89 214733.03 |__sysbench
01:06:43 PM 0 - 490585 36483.49 247768.81 |__sysbench
01:06:43 PM 0 - 490586 35252.29 251989.91 |__sysbench
01:06:43 PM 0 - 490587 35150.46 240639.45 |__sysbench
01:06:43 PM 0 - 490588 33030.28 207896.33 |__sysbench
01:06:43 PM 0 - 490589 34731.19 233100.00 |__sysbench
01:06:43 PM 0 - 490590 39934.86 232202.75 |__sysbench
01:06:43 PM 0 - 490591 36001.83 261024.77 |__sysbench
01:06:43 PM 0 490592 - 0.92 2479.82 pidstat
01:06:43 PM 0 - 490592 0.92 2502.75 |__pidstat
到此,我们就分析出,上下文切换过多的进程是kworker。但是还有一个中断次数过多的问题。
因为中断是发生在内核中的,所以我们需要通过/proc中的信息进行查看。
watch -d cat /proc/interrupts
小结
本篇主要介绍了查看上下文切换的几个常用命令,分别是
vmstat 5 //总体监控
pidstat -w 5 //进程监控
pidstat -w -u 1 //-w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标
pidstat -wt 1 // -wt 参数表示输出线程的上下文切换指标
watch -d cat /proc/interrupts //内核中断指标
而自愿上下文切换边多,说明进程在等待资源,可能发生了IO问题
非自愿上下文切换过多,说明进程在被强制调度,争抢CP
中断次数过多,说明CPU被中断程序占用
相关文章:
【操作系统】聊聊CPU上下文切换实操
如何查看系统的上下文切换情况 上一篇文章我们说了过多的上下文切换,会把CPU时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,那么当出现系统的上下文切换过多的时候,我们如果通过监控指标查看呢。 vmstat 是一个常用的系统性能…...
【java】【SpringBoot】【四】原理篇 bean、starter、核心原理
目录 一、自动配置 1、bean加载方式(复习) 1.1 加载方式-xml方式生命bean 1.2 加载方式-xml注解方式声明bean 1.3 注解方式声明配置类 1.4 FactoryBean 1.5 proxyBeanMethod属性 1.6 使用Import注解导入 1.7 使用上下文对象在容器初始化完毕后注…...
【精品资源】Java毕业设计攻略:从选题到答辩,一站式指南
导读: Java毕业设计是计算机科学与技术专业学生展示其编程能力、问题解决能力和创新思维的重要环节。这篇博客将为您提供一站式的Java毕业设计攻略,帮助您从选题到答辩,顺利完成毕业设计。 一、选题阶段 寻找灵感: 探讨热门技术如…...
文件高效批量重命名,轻松重命名不同类型的文件名并隐藏编号
你是否曾经因为文件名混乱而感到困扰?你是否希望有一种方法可以快速、简单地管理你的文件名?如果你的答案是肯定的,那么我们的产品——文件重命名工具,将是你的完美解决方案! 首先我们要进入文件批量改名高手主页面&a…...
接口的定义与实现
一个c,代表类(class)。 一个c再加上两竖线,代表抽象类。 一个i,代表接口(interface)。 package com.mypackage.oop.demo12;//接口都需要有一个实现类 public interface UserService {//接口中定…...
浅谈低压绝缘监测及定位系统在海上石油平台的研究与应用
安科瑞 华楠 摘要:海上石油平台低压系统与陆地电力系统有很大区别,其属于中性点绝缘系统,在出现单相接地故障时,系统允许带故障正常运行2 h,保证海上重要电气设备不会立即关停。现以渤海某海上平台为例,其…...
Java项目:SSM的食堂点餐系统
作者主页:Java毕设网 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 一、相关文档 系统中的核心用户是系统管理员,管理员登录后,通过管理员菜单来管理后台系统。主要功能有:个人中心、用户管理…...
Linux桌面环境中应用程序无法启动图形交互界面
现象: 点击永中office或者金山office快捷图标无法启动对应的程序。 从命令行执行对应的程序则提示 按照提示安装组件 再次执行命令行程序 原因探析: /opt/Yozosoft/Yozo_Office/Yozo_Writer.bin: error while loading shared libraries: libgdk-x11-2.0.…...
jupyter notebook进不去指定目录怎么办?
首先激活你要使用的虚拟环境 刚开始是现在 (base) C:\Users\lenovo>目录下 直接输入你想进入的盘 (base) C:\Users\lenovo>e:此时再cd (base) C:\Users\lenovo>cd E:\tim\learn_pytorch 就可以进入了 安装3.4.1.15问题 已经有了最新python版本的虚拟环境&#…...
MySQL 高级(进阶) SQL 语句(二) -----存储过程
目录 1 存储过程 1.1 创建存储过程 1.2 调用存储过程 1.3 查看存储过程 1.4 存储过程的参数 1.5 修改存储过程 1.6 删除存储过程 2 条件语句 3 循环语句 1 存储过程 存储过程是一组为了完成特定功能的SQL语句集合。 存储过程在使用过程中是将常用或者复杂的工作预…...
机器学习第十三课--主成分分析PCA
一.高维数据 除了图片、文本数据,我们在实际工作中也会面临更多高维的数据。比如在评分卡模型构建过程中,我们通常会试着衍生出很多的特征,最后就得到上千维、甚至上完维特征;在广告点击率预测应用中,拥有几个亿特征也是常见的事…...
钉钉stream机器人-实操详细教程
支持事件订阅、机器人收消息、卡片回调等功能 优点: 配置简单,不依赖也不需要暴露公网IP,无需向公网开放端口 github官方链接:GitHub - open-dingtalk/dingtalk-stream-sdk-python: Python SDK for DingTalk Stream Mode API, Co…...
设计模式:访问者模式(C++实现)
访问者模式通过将对元素的操作与元素本身分离,使得可以在不修改元素类的情况下定义新的操作。 #include <iostream> #include <vector> #include <algorithm>// 前向声明 class ConcreteElementA; class ConcreteElementB;// 访问者接口 class V…...
Pygame中Sprite的使用方法6-6
4 重新绘制界面 每次碰撞发生后,程序界面需要重新绘制,代码如下所示。 screen.fill(WHITE) all_sprites_list.draw(screen) pygame.display.flip() 其中,screen表示程序的整个界面,将其绘制为白色背景;之后通过all_…...
react多条件查询
1、声明一个filter常量 2.filter接受(condition,data)两个参数 3、调用data里面的filter进行筛选 4、任意一个item当筛选条件 5、使用object.key获取对象所有key 6、对每个key使用Array.prototype.every()方法判断是否满足条…...
2023/09/17
文章目录 1. vscode展开所有代码快捷键ctrl k j2. git删除所有stash或指定stash git stash drop [可选stash名]3. vue在函数默认参数后增加新参数4. git push 添加“-u”参数5. vscode快捷输入符号$的使用6. WebGL之什么是GLB&GLTF文件?7. WebGL之什么是HDR&a…...
Linux centos7压缩包安装mysql-8.0.34 并设置开机自启
下载安装解包 并解压 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.34-linux-glibc2.12-x86_64.tar.xztar -xf mysql-8.0.34-linux-glibc2.12-x86_64.tar.xzmv mysql-8.0.34-linux-glibc2.12-x86_64 /usr/local/mysql初始化数据及安装操作 配置mysql配置文…...
iOS——present相关属性以及dismiss多级的方法
push和present 两者的区别 push: push由视图栈控制,每一个视图都入栈,调用之前的视图则需要出栈,可返回任意一层,一般用于同一业务不同界面之间的切换。 push是由UINavigationController管理的视图控制器堆栈,在wind…...
MinDoc v0.4:轻量级文档在线管理系统
导读SmartWiki 是基于 PHP 框架 laravel 开发的一款文档管理系统。因 PHP 的部署对普通用户来说太复杂,所以改用 Golang 开发。可以方便用户部署和实用。 MinDoc 是一款针对IT团队开发的简单好用的文档管理系统。MinDoc 的前身是 SmartWiki 文档系统。开发缘起是公…...
Appium 全新 2.0 全新跨平台生态,版本特性抢鲜体验!
关于Appium V2 Appium V2 beta版本在2021年发布,从2022年1月1号开始,Appium核心团队不会再维护Appium 1.x版本了,所有近期官方发布的平台驱动(如Android平台的UIAutomator,IOS平台的XCUITest)不再兼容Appi…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...
