如何在类内部封装并管理多个线程实例
技术百科
霞舞
发布时间:2026-01-20
浏览: 次 本文介绍如何将多线程逻辑完全封装进 python 类中,使每个对象自主启动和管理两个并发线程,避免主线程中重复创建和调度线程,提升代码复用性与可维护性。
在面向对象的多线程编程中,一个常见需求是:为每个业务实体(如设备、任务、客户端)创建独立的对象实例,并让每个实例内部并发执行两项职责(例如数据采集 + 状态上报)。若将线程创建逻辑全部暴露在主模块中(如原始示例),会导致对象与线程耦合松散、初始化繁琐、难以扩展。理想方案是将线程生命周期(启动、等待、清理)内聚于类本身。
以下是一个专业、健壮的实现方式:
import threading
import time
class MyObject:
def __init__(self, item_id):
self.item_id = item_id
# 可选:预分配线程引用,提高可读性与调试友好性
self.thread1 = None
self.thread2 = None
def func_one(self):
print(f"[{self.item_id}] func_one started")
time.sleep(1.5) # 模拟耗时操作
print(f"[{self.item_id}] func_one completed")
def func_two(self):
print(f"[{self.item_id}] func_two started")
time.sleep(1.0)
print(f"[{self.item_id}] func_two completed")
def run_threads(self):
"""启动本对象关联的两个线程;线程目标为实例方法,自动绑定 self"""
self.thread1 = threading.Thread(target=self.func_one, name=f"{self.item_id}-func1")
self.thread2 = threading.Thread(target=self.func_two, name=f"{self.item_id}-func2")
# 推荐设置 daemon=False(默认),确保主线程退出前子线程完成工作
# 若需后台守护行为,可显式设为 daemon=True(但 join() 将被忽略)
self.thread1.start()
self.thread2.start()
def join_threads(self):
"""阻塞等待本对象的两个线程全部结束"""
if self.thread1 and self.thread1.is_alive():
self.thread1.join()
if self.thread2 and self.thread2.is_alive():
self.thread2.join()
def is_running(self):
"""辅助方法:检查当前对象是否仍有活跃线程"""
return (self.thread1 and self.thread1.is_alive()) or \
(self.thread2 and self.thread2.is_alive())使用时极为简洁:
# 创建多个独立实例
obj1 = MyObject("item-01")
obj2 = MyObject("item-02")
# 启动各自线程 —— 完全解耦于主线程调度逻辑
obj1.run_threads()
obj2.run_threads()
# 等待所有工作完成
obj1.join_threads()
obj2.join_threads()
print("All objects finished.")✅ 关键设计优势:
- 封装性:run_threads() 和 join_threads() 将线程生命周期完全收归类内,外部仅需调用语义化方法;
- 实例隔离:每个 MyObject 实例拥有专属线程,互不干扰(self.func_one 绑定到对应实例);
- 可扩展性:后续可轻松增加 stop()、status() 或线程池支持,无需修改调用方;
- 健壮性:join_threads() 中加入 is_alive() 检查,避免对已终止线程重复调用 join() 报错。
⚠️ 注意事项:
- 不要在 __init__ 中直接启动线程(可能导致对象未完全构造即执行);
- 避免在 run_threads() 中调用 join() —— 这会阻塞当前线程,违背“并发启动”初衷;
- 若需线程间通信或共享状态,请使用 threading.Event、queue.Queue 等线程安全机制,而非裸露的实例变量;
- 在生产环境建议添加异常捕获(例如在线程目标函数中包装 try/except),防止单个线程崩溃导致整个进程异常退出。
通过这种设计,你获得的不再是一个“带方法的类”,而是一个真正具备并发能力的自治对象——这正是 Python O

# 是一个
# 可选
# 多个
# python
# 绑定
# 若需
# 将被
# 设为
# 并发
# 对象
# 线程
# Event
# 多线程
# 封装
# try
# 装进
# 封装性
# 主线程
# 面向对象
# 请使用
# 代码复用
# 线程生命周期
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何用::实现工具类方法调用_php静态工具类设计
- 如何在 Go 中判断变量是否为函数类型
- Win11怎么关闭系统透明度_Windows11个
- Win11怎么制作U盘启动盘_Win11原版系统安
- Win11怎么更改任务栏颜色_Windows11个
- Win11怎么查看wifi信号强度_检测Windo
- Win11 C盘满了怎么清理 Win11磁盘清理和
- Win10系统怎么查看显卡温度_Win10任务管理
- ACF 教程:如何正确更新嵌套在多层 Group
- 如何用正则与预处理结合精准拦截拼接式垃圾域名
- Win11怎么设置ipv4地址_Windows 1
- Win11怎么关闭任务栏小图标_Windows11
- Win11快速助手怎么用_Win11远程协助连接教
- 如何在 Go 中创建包含映射(map)的切片(sl
- Windows怎样关闭开始菜单广告_Windows
- Windows10系统怎么查看系统版本_Win10
- PHP怎么接收URL中的锚点参数_获取#后面参数值
- Mac怎么设置鼠标滚动速度_Mac鼠标设置详细参数
- Win11怎么设置默认浏览器Chrome_Wind
- 如何使用Golang实现云原生应用弹性伸缩_自动应
- Mac怎么开启“任何来源”_Mac安装未签名应用的
- 如何在Golang中处理二进制数据_Golang
- Win11怎么开启上帝模式_创建Windows 1
- 如何在 IIS 上为 ASP.NET 6 应用排除
- Win10怎样清理C盘Steam游戏缓存_Win1
- 如何在Golang中使用闭包_封装变量与函数作用域
- Win11怎么开启游戏工具栏_Windows11
- Win10怎样卸载iTunes_Win10卸载iT
- c++怎么操作redis数据库_c++ hired
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- Win11如何设置自动关机 Win11定时关机命令
- 如何自定义Windows终端的默认配置文件?(Po
- Windows服务无法启动错误1067是什么_进程
- 如何使用Golang实现函数指针_函数变量与回调示
- 如何在 Go 项目开发中正确处理本地包导入与远程模
- Windows如何使用注册表查找和删除项?(reg
- Win10怎么卸载爱奇艺_Win10彻底卸载爱奇艺
- PHP cURL GET请求:正确设置请求头与身份
- Windows 11怎么设置默认解压软件_Wind
- 如何在 Pandas 中按元素交集合并两列字符串
- c# 如何用c#实现一个支持优先级的任务队列
- LINUX怎么进行文本内容搜索_Linux gre
- php嵌入式日志记录怎么实现_php将硬件数据写入
- Win11如何关闭小娜Cortana Win11禁
- WindowsUSB驱动安装异常怎么办_USB驱动
- 如何使用Golang实现微服务状态监控_Golan
- c++怎么设置线程优先级与cpu亲和性_c++ 多
- php中常量能用::访问吗_类常量与作用域操作符使
- Win11视频默认播放器怎么改_Win11关联第三
- Win11怎么设置单手模式_Win11触控键盘布局

QQ客服