当前位置: 首页 > news >正文

【Python学习笔记】41.Python3 多线程

前言

本章介绍Python的多线程。

Python3 多线程

多线程类似于同时执行多个不同程序,多线程运行有如下优点:

  • 使用线程可以把占据长时间的程序中的任务放到后台去处理。
  • 用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。
  • 程序的运行速度可能加快。
  • 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。

每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。

指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。

  • 线程可以被抢占(中断)。
  • 在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) – 这就是线程的退让。

线程可以分为:

  • 内核线程:由操作系统内核创建和撤销。
  • 用户线程:不需要内核支持而在用户程序中实现的线程。

Python3 线程中常用的两个模块为:

  • _thread
  • threading(推荐使用)

thread 模块已被废弃。用户可以使用 threading 模块代替。所以,在 Python3 中不能再使用"thread" 模块。为了兼容性,Python3 将 thread 重命名为 “_thread”。

开始学习Python线程

Python中使用线程有两种方式:函数或者用类来包装线程对象。

函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下:

_thread.start_new_thread ( function, args[, kwargs] )

参数说明:

  • function - 线程函数。
  • args - 传递给线程函数的参数,他必须是个tuple类型。
  • kwargs - 可选参数。

实例

#!/usr/bin/python3import _thread
import time# 为线程定义一个函数
def print_time( threadName, delay):count = 0while count < 5:time.sleep(delay)count += 1print ("%s: %s" % ( threadName, time.ctime(time.time()) ))# 创建两个线程
try:_thread.start_new_thread( print_time, ("Thread-1", 2, ) )_thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:print ("Error: 无法启动线程")while 1:pass

执行以上程序输出结果如下:

Thread-1: Wed Jan  5 17:38:08 2022
Thread-2: Wed Jan  5 17:38:10 2022
Thread-1: Wed Jan  5 17:38:10 2022
Thread-1: Wed Jan  5 17:38:12 2022
Thread-2: Wed Jan  5 17:38:14 2022
Thread-1: Wed Jan  5 17:38:14 2022
Thread-1: Wed Jan  5 17:38:16 2022
Thread-2: Wed Jan  5 17:38:18 2022
Thread-2: Wed Jan  5 17:38:22 2022
Thread-2: Wed Jan  5 17:38:26 2022

执行以上程后可以按下 ctrl-c 退出。

线程模块

Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。

_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。

threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:

  • threading.currentThread(): 返回当前的线程变量。
  • threading.enumerate():
    返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount():
    返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

  • run(): 用以表示线程活动的方法。
  • start():启动线程活动。
  • join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
  • isAlive(): 返回线程是否活动的。
  • getName(): 返回线程名。
  • setName(): 设置线程名。

使用 threading 模块创建线程

我们可以通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法:

实例

#!/usr/bin/python3import threading
import timeexitFlag = 0class myThread (threading.Thread):def __init__(self, threadID, name, delay):threading.Thread.__init__(self)self.threadID = threadIDself.name = nameself.delay = delaydef run(self):print ("开始线程:" + self.name)print_time(self.name, self.delay, 5)print ("退出线程:" + self.name)def print_time(threadName, delay, counter):while counter:if exitFlag:threadName.exit()time.sleep(delay)print ("%s: %s" % (threadName, time.ctime(time.time())))counter -= 1# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)# 开启新线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("退出主线程")

以上程序执行结果如下;

开始线程:Thread-1
开始线程:Thread-2
Thread-1: Wed Jan  5 17:34:54 2022
Thread-2: Wed Jan  5 17:34:55 2022
Thread-1: Wed Jan  5 17:34:55 2022
Thread-1: Wed Jan  5 17:34:56 2022
Thread-2: Wed Jan  5 17:34:57 2022
Thread-1: Wed Jan  5 17:34:57 2022
Thread-1: Wed Jan  5 17:34:58 2022
退出线程:Thread-1
Thread-2: Wed Jan  5 17:34:59 2022
Thread-2: Wed Jan  5 17:35:01 2022
Thread-2: Wed Jan  5 17:35:03 2022
退出线程:Thread-2
退出主线程

线程同步

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。

使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。如下:

多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。

考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。

那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。

锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。

经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。

实例

#!/usr/bin/python3import threading
import timeclass myThread (threading.Thread):def __init__(self, threadID, name, delay):threading.Thread.__init__(self)self.threadID = threadIDself.name = nameself.delay = delaydef run(self):print ("开启线程: " + self.name)# 获取锁,用于线程同步threadLock.acquire()print_time(self.name, self.delay, 3)# 释放锁,开启下一个线程threadLock.release()def print_time(threadName, delay, counter):while counter:time.sleep(delay)print ("%s: %s" % (threadName, time.ctime(time.time())))counter -= 1threadLock = threading.Lock()
threads = []# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)# 开启新线程
thread1.start()
thread2.start()# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)# 等待所有线程完成
for t in threads:t.join()
print ("退出主线程")

执行以上程序,输出结果为:

开启线程: Thread-1
开启线程: Thread-2
Thread-1: Wed Jan  5 17:36:50 2022
Thread-1: Wed Jan  5 17:36:51 2022
Thread-1: Wed Jan  5 17:36:52 2022
Thread-2: Wed Jan  5 17:36:54 2022
Thread-2: Wed Jan  5 17:36:56 2022
Thread-2: Wed Jan  5 17:36:58 2022
退出主线程

线程优先级队列( Queue)

Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue。

这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。

Queue 模块中的常用方法:

  • Queue.qsize() 返回队列的大小
  • Queue.empty() 如果队列为空,返回True,反之False
  • Queue.full() 如果队列满了,返回True,反之False
  • Queue.full 与 maxsize 大小对应
  • Queue.get([block[, timeout]])获取队列,timeout等待时间
  • Queue.get_nowait() 相当Queue.get(False)
  • Queue.put(item) 写入队列,timeout等待时间
  • Queue.put_nowait(item) 相当Queue.put(item, False)
  • Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
  • Queue.join() 实际上意味着等到队列为空,再执行别的操作

实例

#!/usr/bin/python3import queue
import threading
import timeexitFlag = 0class myThread (threading.Thread):def __init__(self, threadID, name, q):threading.Thread.__init__(self)self.threadID = threadIDself.name = nameself.q = qdef run(self):print ("开启线程:" + self.name)process_data(self.name, self.q)print ("退出线程:" + self.name)def process_data(threadName, q):while not exitFlag:queueLock.acquire()if not workQueue.empty():data = q.get()queueLock.release()print ("%s processing %s" % (threadName, data))else:queueLock.release()time.sleep(1)threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threads = []
threadID = 1# 创建新线程
for tName in threadList:thread = myThread(threadID, tName, workQueue)thread.start()threads.append(thread)threadID += 1# 填充队列
queueLock.acquire()
for word in nameList:workQueue.put(word)
queueLock.release()# 等待队列清空
while not workQueue.empty():pass# 通知线程是时候退出
exitFlag = 1# 等待所有线程完成
for t in threads:t.join()
print ("退出主线程")

以上程序执行结果:

开启线程:Thread-1
开启线程:Thread-2
开启线程:Thread-3
Thread-3 processing One
Thread-1 processing Two
Thread-2 processing Three
Thread-3 processing Four
Thread-1 processing Five
退出线程:Thread-3
退出线程:Thread-2
退出线程:Thread-1
退出主线程

相关文章:

【Python学习笔记】41.Python3 多线程

前言 本章介绍Python的多线程。 Python3 多线程 多线程类似于同时执行多个不同程序&#xff0c;多线程运行有如下优点&#xff1a; 使用线程可以把占据长时间的程序中的任务放到后台去处理。用户界面可以更加吸引人&#xff0c;比如用户点击了一个按钮去触发某些事件的处理…...

Windows 版本ffmpeg编译概述

在使用ffmpeg过程当中&#xff0c;ffmpeg在Linux(包括mac,android)编译非常容易,直接configure,make即可&#xff0c;Android需要交叉编译,在windows就比较麻烦&#xff0c;庆幸的是ffmpeg官方提供已编译好Windows版本的二进制库&#xff08;http://ffmpeg.org/download.html#b…...

NETCore下CI/CD之自动化测试 (详解篇)

NETCore下CI/CD之自动化测试 &#xff08;详解篇&#xff09; 目录&#xff1a;导读 前言 安装JDK 安装 Tomcat 首先&#xff0c;我们需要指定 Tomcat.PID 进程文件&#xff0c;进入 /usr/local/tomcat/bin&#xff0c;编辑文件 增加 tomcat 账户并赋予权限 防止Jeknins…...

Hoeffding不等式剪枝方法

在基于物品的协通过滤算法中&#xff0c;当用户历史行为数据有很多时&#xff0c;对计算会有很大挑战&#xff0c;对此可以使用剪枝对数据进行化简来达到减少计算量。     不是每个物品对都需要进行增量计算。对于两个物品的相似度&#xff0c;每次更新都能够得到一个新的相…...

【算法】数组中的重复数字问题

数组中的重复数据 数组中重复的数字 错误的集合 以第三题&#xff0c;错误的集合为例 对于这样的问题&#xff0c;有很简单的解决方式&#xff0c;先遍历一次数组&#xff0c;用一个哈希表记录每个数字出现的次数&#xff0c;然后遍历一次 [1…N]&#xff0c;看看那个元素重…...

数值方法笔记2:解决非线性方程

1. 不动点定理及其条件验证2. 收敛阶、收敛检测与收敛加速2.1 如何估计不动点迭代的收敛阶xk1g(xk){x}_{{k}1}{g}\left({x}_{{k}}\right)xk1​g(xk​)2.2 给定精度的情况下&#xff0c;如何预测不动点迭代需要迭代的次数2.3 如何加快收敛的速度2.4 停止不定点迭代的条件2.5 不动…...

基于SpringBoot的在线文档管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏…...

软件体系结构(期末复习)

文章目录软件体系结构软件体系结构概论软件体系结构建模软件体系结构风格统一建模语言基于体系结构的软件开发软件体系结构 软件体系结构概论 软件危机是指计算机软件的开发和维护过程中遇到的一系列严重问题。 软件危机的表现: 软件危机的原因: 软件工程的基本要素&#xf…...

[vue3] pinia的基本使用

使用Pinia npm install piniastore文件里index.js import { createPinia } from piniaconst pinia createPinia()export default piniamain.js导入并引用 import { createApp } from vue import App from ./App.vue import pinia from ./storescreateApp(App).use(pinia).m…...

进程和线程详解

在计算机领域中&#xff0c;进程和线程是非常重要的概念。了解进程和线程是软件开发的基础&#xff0c;也是计算机科学教育中的一部分。本文将介绍进程和线程的概念、区别和应用。 一、什么是进程 在计算机科学中&#xff0c;进程是正在执行的程序实例。一个进程可以由一个或…...

《刀锋》读书笔记

刀锋&#xff08;毛姆长篇作品精选&#xff09;毛姆50个笔记点评认为好看的确是完美的结局。《刀锋》里面的人每个人都以自己的方式生活着。艾略特的势利&#xff0c;拉里的自由&#xff0c;伊莎贝尔的现实&#xff0c;苏珊的清醒&#xff0c;索菲的堕落&#xff0c;至于“我”…...

nginx中的ngx_modules

ngx_modules和ngx_module_names是configure脚本生成的&#xff0c;是在objs/ngx_modules.c文件中与其生成的相关的脚本文件相关的变量在options脚本中定义了objs目录的变量NGX_OBJSobjs在init脚本中定义的最终存放ngx_modules的文件 NGX_MODULES_C$NGX_OBJS/ngx_modules.c2. 处…...

设计模式之访问者模式

什么是访问者模式 访问者模式提供了一个作用于某对象结构中的各元素的操作表示&#xff0c;他使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。     访问者模式主要包含以下几个角色&#xff1a;         Vistor(抽象访问者)&#xff1a;为对象结…...

Go项目(三)

文章目录用户微服务表结构查表web 服务跨域问题图形验证码短信用户注册服务中心注册 grpc 服务动态获取端口负载均衡配置中心启动项目小结用户微服务 作为系统的第一个微服务&#xff0c;开发的技术点前面已经了解了一遍&#xff0c;虽有待补充&#xff0c;但急需实战这里主要…...

CTK学习:(一)编译CTK

CTK插件框架简介 CTK Plugin Framework是用于C++的动态组件系统,以OSGi规范为模型。在此框架下,应用程序由不同的组件组成,遵循面向服务的方法。 ctk是一个开源项目,Github 地址:https://github.com/commontk。 源码地址commontk/CTK: A set of common support code for…...

15种NLP数据增强方法总结与对比

数据增强的方法 数据增强&#xff08;Data Augmentation&#xff0c;简称DA&#xff09;&#xff0c;是指根据现有数据&#xff0c;合成新数据的一类方法。毕竟数据才是真正的效果天花板&#xff0c;有了更多数据后可以提升效果、增强模型泛化能力、提高鲁棒性等。然而由于NLP…...

Python每日一练(20230219)

目录 1. 循环随机取数组直到得出指定数字&#xff1f; 2. 旋转链表 3. 区间和的个数 1. 循环随机取数组直到得出指定数字&#xff1f; 举个例子&#xff1a; 随机数字范围&#xff1a;0~100 每组数字量&#xff1a;6&#xff08;s1,s2,s3,s4,s5,s6&#xff09; 第二轮开始随…...

vTESTstudio - VT System CAPL Functions - VT7001

vtsSerialClose - 关闭VT系统通道的串行端口功能&#xff1a;关闭由系统变量命名空间指定的VT系统通道的串行端口。Target&#xff1a;目标通道变量空间名称&#xff0c;例如&#xff1a;VTS::ECUPowerSupply返回值&#xff1a;0&#xff1a;成功重置目标通道最大和最小值-1&am…...

「可信计算」论文初步解读

可信计算组织&#xff08;Ttrusted Computing Group,TCG&#xff09;是一个非盈利的工业标准组织&#xff0c;它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立&#xff0c;并采纳了由可信计算平台联盟&#xff08;the Trusted Computing Platform Alli…...

CSDN 算法技能树 蓝桥杯-基础 刷题+思考总结

切面条-蓝桥杯-基础-CSDN算法技能树https://edu.csdn.net/skill/algorithm/algorithm-530255df51be437b967cbc4524fe66ea?category188 目录 切面条 大衍数列 门牌制作 方阵转置 微生物增殖 成绩统计 星系炸弹 判断闰年的依据: 特别数的和 *日志统计*&#xff08;双指…...

信小程序点击按钮绘制定制转发分享图

1. 说明 先上代码片断分享链接&#xff1a; https://developers.weixin.qq.com/s/vl3ws9mA72GG 使用 painter 画图 按钮传递定制化信息 效果如下&#xff1a; 2. 关键代码说明 文件列表如下&#xff1a; {"usingComponents": {"painter": "/com…...

Python自动化测试-使用Pandas来高效处理测试数据

Python自动化测试-使用Pandas来高效处理测试数据 目录&#xff1a;导读 一、思考 二、使用pandas来操作Excel文件 三、使用pandas来操作csv文件 四、总结 一、思考 1.Pandas是什么&#xff1f; 功能极其强大的数据分析库可以高效地操作各种数据集 csv格式的文件Excel文件H…...

语音增强学习路线图Roadmap

语音增强算是比较难的研究领域&#xff0c;从入门到精通有很多台阶&#xff0c;本文介绍一些有价值的书籍&#xff0c;值得反复阅读。主要分为基础类和进阶类书籍&#xff0c;大多都是理论和实践相结合的书籍&#xff0c;编程实践是抓手,让知识和基础理论变扎实。基础书籍《信号…...

nginx配置ssl实现https访问

文章目录一、介绍二、创建证书1、OpenSSL创建自签名密钥和证书三、nginx配置四、开放端口一、介绍 nginx配置ssl证书&#xff0c;实现https访问&#xff0c;可以使用自签名SSL证书或者购买机构颁发的证书两种方式参考链接 https://blog.csdn.net/weixin_39198406/article/deta…...

JavaScript 语句

JavaScript 语句向浏览器发出的命令。语句的作用是告诉浏览器该做什么。JavaScript 语句JavaScript 语句是发给浏览器的命令。这些命令的作用是告诉浏览器要做的事情。下面的 JavaScript 语句向 id"demo" 的 HTML 元素输出文本 "Hello Dolly" &#xff1a;…...

将古老的ASP项目转换为PHP初探

ASP 是一种服务器端脚本语言&#xff0c;主要用于开发动态 Web 应用程序。ASP 可以在服务器上执行代码&#xff0c;并将结果返回给客户端浏览器&#xff0c;实现动态生成 Web 页面的功能。ASP 代码通常包含在 <% %> 标记中&#xff0c;以下是一个简单的 ASP 程序示例&…...

数据结构复习(七)模板类封装实现不带头结点的单链表

一、代码 二、总结 一、代码 #include<iostream> using namespace std;template<class T> struct ListNode {T _data;ListNode* next;ListNode(const T& data T()){_data data;next nullptr;}~ListNode(){next nullptr;} };template<class T> class…...

IDEA插件 RestfulTool插件——Restful服务开发辅助工具集

IDEA插件 RestfulTool插件——Restful服务开发辅助工具集 目录IDEA插件 RestfulTool插件——Restful服务开发辅助工具集1.插件介绍2.安装方式3.使用方法1.插件介绍 RestfulTool插件。一套 Restful 服务开发辅助工具集&#xff1a; 提供了一个 Services tree 的显示窗口 双击 …...

2023年全国最新会计专业技术资格精选真题及答案1

百分百题库提供会计专业技术资格考试试题、会计考试预测题、会计专业技术资格考试真题、会计证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 11.下列各项中&#xff0c;影响企业利润表“利润总额”项目的是&#xff08;&…...

Linux 配置RAID组

目录 配置RAID&#xff08;软件RAID&#xff09; 创建RAID组 RAID中出现坏盘如何操作 RAID 添加热备盘 删除RAID组 RAID所解决的问题 提升硬盘的I/O吞吐率 提高硬盘的读写能力 提高硬盘的安全性 进行备份 减少硬盘成本 RAID级别 存储RAID——RAID级别_静下心来敲木鱼的博…...

传奇广告网站怎么做/全网整合营销推广方案

翻译原文链接 转帖&#xff0f;转载请注明出处 原文链接medium.com 发表于2017/08/30 我在防垃圾邮件&#xff0c;防病毒和防恶意软件领域已经工作了15年&#xff0c;前后在好几个公司任职。我知道这些系统最后都会因为要处理海量的数据而变得非常复杂。 我现在是smsjunk.com的…...

网站营销方式/今日十大热点新闻头条

写在前面 本文首发于公众号&#xff1a;符合预期的CoyPan 最近做了一个移动端活动页的需求&#xff0c;大概就是diy一个页面。用户可以对物料进行拖动、缩放、旋转&#xff0c;来达到diy的目的。用DOM来实现是不现实的&#xff0c;我采用了canvas来实现和用户的交互。开发过程中…...

北京公司模板网站好/石家庄网络关键词排名

前面的直接插入算法&#xff0c;以抓牌为例&#xff0c;假设手气比较好&#xff0c;抓牌的顺序是从A直到K&#xff0c;那么在这整个过程中都无需进行任何的插入动作&#xff0c;只需要将每次抓到的牌放在最后即可。假设现在手上已经抓到的牌的顺序中逆序比较少&#xff0c;则抓…...

网站 公司/朋友圈推广文案

spark能跑Python么&#xff1f;spark是可以跑Python程序的。python编写好的算法&#xff0c;或者扩展库的&#xff0c;比如sklearn都可以在spark上跑。直接使用spark的mllib也是可以的&#xff0c;大部分算法都有。Spark 是一个通用引擎&#xff0c;可用它来完成各种各样的运算…...

宁波做网站的大公司排名/如何优化网站

在asp.net mvc2.0中做开发&#xff0c;model 中包含泛型的字段字段的情况很常见&#xff0c;但网上一直很难找到相关的例子&#xff0c;没办法&#xff0c;只能自己摸索。分享如下。 代码&#xff1a; <table class"checkBoxList"> …...

做网站订单/推广普通话手抄报内容简短

OSD进程的启动停止&#xff1a;https://blog.csdn.net/bandaoyu/article/details/119894927 1. OSD概念 OSD&#xff1a;Object Storage Device&#xff0c;主要负责响应客户端请求返回具体数据的守护进程&#xff0c;一般一个集群会有多个OSD&#xff0c;每一块盘都会对应一个…...