Python入门:Python3 threading模块全面学习教程
Python入门Python3 threading模块全面学习教程Python入门Python3 threading模块全面学习教程本文是 Python threading 模块的入门到实战指南聚焦该模块解决单线程 I/O 阻塞、提升程序并发效率的核心作用。内容先介绍两种线程创建方式继承 threading.Thread 类并重写 run () 方法、通过 Thread 构造函数传目标函数再讲解线程同步工具Lock、Condition 等解决共享资源竞争与线程安全通信方式queue.Queue 传递数据还包含核心 API 速查及生产者 - 消费者模型实战案例。同时提醒 GIL 对 CPU 密集型任务的限制、线程安全要点与合理控制线程数量的重要性助力开发者掌握多线程编程适用于 I/O 密集场景也提及后续可拓展学习线程池或 multiprocessing 模块。前言Python作为一门简洁、易读、功能强大的编程语言其基础语法是入门学习的核心。掌握好基础语法能为后续的编程实践打下坚实的基础。本文将全面讲解Python3的基础语法知识适合编程初学者系统学习。Python以其简洁优雅的语法和强大的通用性成为当今最受欢迎的编程语言。本专栏旨在系统性地带你从零基础入门到精通Python核心。无论你是零基础小白还是希望进阶的专业开发者都将通过清晰的讲解、丰富的实例和实战项目逐步掌握语法基础、核心数据结构、函数与模块、面向对象编程、文件处理、主流库应用如数据分析、Web开发、自动化以及面向对象高级特性最终具备独立开发能力和解决复杂问题的思维高效应对数据分析、人工智能、Web应用、自动化脚本等广泛领域的实际需求。 点击进入Python入门专栏Python凭借简洁易读的语法是零基础学习编程的理想选择。本专栏专为初学者设计系统讲解Python核心基础变量、数据类型、流程控制、函数、文件操作及常用库入门。通过清晰示例与实用小项目助你快速掌握编程思维打下坚实根基迈出自动化办公、数据分析或Web开发的第一步。 点击进入Python小游戏实战专栏 寓教于乐用Python亲手打造经典小游戏本专栏通过开发贪吃蛇、飞机大战、猜数字、简易版俄罗斯方块等趣味项目在实践中掌握Python核心语法、面向对象编程、事件处理、图形界面如Pygame等关键技能将枯燥的代码学习转化为可见的成果让学习编程充满乐趣与成就感快速提升实战能力。 点击进入Python小工具实战专栏告别重复劳动用Python打造效率神器本专栏教你开发文件批量处理、自动邮件通知、简易爬虫、桌面提醒、密码生成器、天气查询等实用小工具。聚焦os、shutil、requests、smtplib、schedule等核心库通过真实场景案例快速掌握自动化脚本编写技巧解放双手显著提升工作与生活效率让代码真正服务于你的日常。 点击进入Python爬虫实战专栏解锁网络数据宝库本专栏手把手教你使用Python核心库如requests、BeautifulSoup、Scrapy构建高效爬虫。从基础网页解析到动态页面抓取、数据存储CSV/数据库、反爬策略应对及IP代理使用通过实战项目如电商比价、新闻聚合、图片采集、舆情监控掌握合法合规获取并利用网络数据的核心技能让数据成为你的超能力。 点击进入Python项目实战专栏告别碎片化学习挑战真实项目本专栏精选Web应用开发Flask/Django、数据分析可视化、自动化办公系统、简易爬虫框架、API接口开发等综合项目。通过需求分析、架构设计、编码实现、测试部署的全流程深入掌握工程化开发、代码复用、调试排错与团队协作核心能力积累高质量作品集真正具备解决复杂问题的Python实战经验。 前篇文章咱们练习了 Python3 CSV模块全面学习教程 如果忘记了可以去重温一下不停的重复敲击基础代码有助于让你更加熟练掌握一门语言。今天咱们继续学习 Python3 threading模块全面学习教程下面开始吧在Python开发中面对I/O密集型任务如网络请求、文件读写时单线程的阻塞问题会严重影响程序效率。而threading模块作为Python标准库中实现多线程编程的核心工具能让程序在等待I/O的同时执行其他任务大幅提升并发能力。本文将从基础概念出发逐步讲解threading模块的使用方法、核心组件及实战案例帮助你快速掌握多线程编程。一、为什么需要多线程单线程的痛点在单线程程序中任务会顺序执行如果某个任务需要等待比如等待网络响应、读取大文件整个程序会被“卡住”直到该任务完成才能继续执行下一个任务。举个例子假设我们需要下载3个文件每个文件下载耗时2秒。单线程执行需要2226秒而多线程可以让3个下载任务“并行”实际是并发执行总耗时接近2秒。这就是多线程的核心价值利用任务等待时间并行处理多个任务提高程序整体效率。二、threading模块基础如何创建线程threading模块提供两种主流的线程创建方式适用于不同场景。所有示例代码均可直接复制运行建议边学边练。2.1 方式1继承threading.Thread类面向对象通过继承threading.Thread类并重写其run()方法线程执行的核心逻辑可以创建自定义线程。示例代码importthreading# 1. 自定义线程类继承ThreadclassMyThread(threading.Thread):# 2. 重写run()方法线程启动后会自动执行此方法defrun(self):print(f线程{self.name}开始执行)# self.name是线程名称默认自动生成# 此处编写线程的核心逻辑如文件读取、网络请求foriinrange(3):print(f线程{self.name}执行中{i})print(f线程{self.name}执行结束)# 3. 创建线程实例thread1MyThread()thread2MyThread()# 4. 启动线程必须调用start()而非直接调用run()thread1.start()thread2.start()# 5. 等待线程执行完毕主线程阻塞直到子线程结束thread1.join()thread2.join()print(主线程结束)# 所有子线程执行完后才会打印关键说明start()启动线程底层会调用run()方法不可直接调用run()否则会以单线程方式执行。join(timeoutNone)主线程等待子线程结束timeout为可选超时时间单位秒。self.name线程名称可在创建实例时指定如MyThread(nameDownload-1)。2.2 方式2使用threading.Thread构造函数函数式如果不需要复杂的线程类扩展可直接将目标函数传给threading.Thread的target参数更简洁高效。示例代码importthreading# 1. 定义线程要执行的函数deftask(name):print(f线程{name}开始执行)# 核心逻辑foriinrange(3):print(f线程{name}执行中{i})print(f线程{name}执行结束)# 2. 创建线程实例target指定函数args指定函数参数元组形式thread1threading.Thread(targettask,args(Worker-1,))# args必须是元组单个参数需加逗号thread2threading.Thread(targettask,args(Worker-2,))# 3. 启动线程thread1.start()thread2.start()# 4. 等待线程结束thread1.join()thread2.join()print(主线程结束)适用场景简单的单任务场景如单个函数执行无需自定义线程类的额外属性或方法。三、线程同步解决共享资源竞争问题多线程同时访问共享资源如全局变量、公共列表时会出现“数据不一致”的问题称为“数据竞争”。例如10个线程同时对一个全局计数器加1最终结果可能小于10。threading模块提供锁Lock机制确保同一时间只有一个线程能访问共享资源实现线程同步。3.1 基础锁Lock的使用Lock是最常用的同步工具核心逻辑是“获取锁→操作共享资源→释放锁”。推荐使用with语句自动管理锁无需手动调用release()避免忘记释放导致死锁。示例代码锁保护全局计数器importthreading# 共享资源全局计数器count0# 创建锁对象lockthreading.Lock()# 线程执行的函数对计数器加1defincrement():globalcount# 声明使用全局变量# with lock自动获取锁代码块执行完后自动释放锁withlock:tempcount# 读取共享资源temp1# 修改counttemp# 写回共享资源# 创建10个线程同时执行incrementthreads[threading.Thread(targetincrement)for_inrange(10)]# 启动所有线程fortinthreads:t.start()# 等待所有线程结束fortinthreads:t.join()print(f最终计数器值{count})# 输出10无锁时可能小于10关键说明无锁时多个线程可能同时读取count0并各自加1后写回导致最终结果小于10。有锁时with lock代码块内的操作是“原子性”的同一时间只有一个线程执行确保数据一致。3.2 其他常用同步工具除了基础锁threading模块还提供多种高级同步工具适用于复杂场景工具类作用适用场景threading.RLock可重入锁同一线程可多次获取锁避免自身死锁嵌套锁场景如函数A调用函数B两者都需要锁threading.Event事件通知通过set()/clear()控制线程阻塞/唤醒线程间简单通知如“任务完成”信号threading.Condition条件变量结合锁和事件支持“等待-通知”机制生产者-消费者模型、复杂线程协调threading.Semaphore信号量控制同时访问资源的线程数量如限制5个线程同时下载资源有限场景如数据库连接池threading.BoundedSemaphore有界信号量防止信号量计数超过初始值更安全严格限制资源访问次数四、线程间通信用Queue安全传递数据多线程间需要传递数据时直接操作共享列表/字典可能导致数据混乱。queue.Queue线程安全的队列是最佳选择——它内置同步机制确保多个线程安全地读写数据。示例代码Queue实现多线程任务分发importthreadingimportqueueimporttime# 1. 定义工作线程函数从队列中获取任务并处理defworker(worker_name,task_queue):whileTrue:try:# 从队列获取任务blockFalse队列空时抛出Empty异常tasktask_queue.get(blockFalse)print(f[{worker_name}] 处理任务{task})time.sleep(1)# 模拟任务处理耗时task_queue.task_done()# 标记任务完成告知队列此任务已处理exceptqueue.Empty:# 队列空时退出循环print(f[{worker_name}] 所有任务处理完毕)break# 2. 创建队列并添加任务task_queuequeue.Queue()foriinrange(5):# 添加5个任务task_queue.put(fTask-{i1})# 3. 创建2个工作线程thread1threading.Thread(targetworker,args(Worker-1,task_queue))thread2threading.Thread(targetworker,args(Worker-2,task_queue))# 4. 启动线程thread1.start()thread2.start()# 5. 等待队列中所有任务被处理完毕阻塞直到所有task_done()被调用task_queue.join()print(所有任务处理完成主线程结束)关键说明task_queue.get()获取队列中的任务默认阻塞队列空时等待。task_queue.task_done()必须在任务处理完后调用否则task_queue.join()会一直阻塞。queue.Empty队列空时抛出的异常用于退出工作线程循环。五、threading模块核心API速查为了方便日常开发整理了threading模块最常用的类、方法及属性建议收藏5.1 核心类类名说明示例代码threading.Thread线程类创建和管理线程t threading.Thread(targetfunc)threading.Lock基础互斥锁防止共享资源竞争lock threading.Lock()threading.Event事件对象控制线程阻塞/唤醒event threading.Event()threading.Condition条件变量结合锁和事件的高级同步工具cond threading.Condition()threading.Semaphore信号量限制并发线程数sem threading.Semaphore(3)threading.Timer定时器线程延迟指定时间后执行函数timer threading.Timer(5, func)threading.local线程局部数据每个线程存储独立数据避免共享local_data threading.local()5.2 Thread对象常用方法/属性方法/属性说明示例代码start()启动线程t.start()join(timeoutNone)主线程等待子线程结束timeout为超时时间t.join(10)is_alive()判断线程是否正在运行if t.is_alive(): print(Running)name线程名称可修改t.name Download-Threaddaemon守护线程标志True时主线程退出子线程自动结束t.daemon Trueident线程唯一标识符未启动时为Noneprint(t.ident)5.3 模块级函数函数名说明示例代码active_count()返回当前活跃的线程数量print(threading.active_count())current_thread()返回当前执行的线程对象print(threading.current_thread().name)enumerate()返回所有活跃线程的列表for t in threading.enumerate(): print(t.name)main_thread()返回主线程对象print(threading.main_thread().name)六、实战案例生产者-消费者模型Condition实现生产者-消费者模型是多线程编程的经典场景生产者生成数据并放入队列队列满时等待。消费者从队列中获取数据并处理队列空时等待。使用threading.Condition可高效实现此模型避免频繁轮询队列状态。示例代码importthreadingimportrandomimporttime# 共享队列存储生产的数据product_queue[]# 队列最大容量MAX_SIZE5# 创建Condition对象内置锁condthreading.Condition()# 生产者线程生成随机数放入队列defproducer():for_inrange(10):# 生产10个数据withcond:# 自动获取锁# 队列满时等待消费者消费释放锁阻塞whilelen(product_queue)MAX_SIZE:print(队列已满生产者等待...)cond.wait()# 释放锁并阻塞直到被notify()唤醒# 生产数据productrandom.randint(1,100)product_queue.append(product)print(f生产者生产{product}当前队列{product_queue})# 唤醒一个等待的消费者告知队列有数据了cond.notify()time.sleep(0.5)# 模拟生产耗时# 消费者线程从队列获取数据并处理defconsumer():for_inrange(10):# 消费10个数据withcond:# 队列空时等待生产者生产释放锁阻塞whilenotproduct_queue:print(队列为空消费者等待...)cond.wait()# 消费数据productproduct_queue.pop(0)print(f消费者消费{product}当前队列{product_queue})# 唤醒一个等待的生产者告知队列有空间了cond.notify()time.sleep(1)# 模拟消费耗时# 启动生产者和消费者线程producer_threadthreading.Thread(targetproducer)consumer_threadthreading.Thread(targetconsumer)producer_thread.start()consumer_thread.start()# 等待线程结束producer_thread.join()consumer_thread.join()print(生产消费完成)关键细节cond.wait()释放内置锁并阻塞线程直到其他线程调用notify()或notify_all()。while循环判断队列状态避免“虚假唤醒”线程被唤醒但队列状态未改变不可用if判断。cond.notify()唤醒一个等待的线程若需唤醒所有线程用cond.notify_all()。七、注意事项避免多线程踩坑全局解释器锁GIL的限制Python的GILGlobal Interpreter Lock会强制同一时间只有一个线程执行Python字节码。因此I/O密集型任务网络、文件读写多线程能大幅提升效率线程等待I/O时释放GIL其他线程可执行。CPU密集型任务如大量计算多线程无法实现真正并行建议用multiprocessing模块多进程。线程安全优先所有共享资源全局变量、列表、字典必须通过锁或线程安全工具如Queue访问避免数据竞争。合理控制线程数量线程创建过多会消耗大量内存和CPU资源甚至导致程序崩溃。建议I/O密集型任务线程数可设为2*CPU核心数 1。复杂场景使用concurrent.futures.ThreadPoolExecutor线程池自动管理线程。守护线程的使用场景当daemonTrue时主线程退出后守护线程会自动终止无需等待。适用于“辅助任务”如日志打印不适用于“核心任务”如数据写入。八、总结threading模块是Python处理并发任务的核心工具尤其适合I/O密集型场景。本文从线程创建、同步、通信到实战案例覆盖了threading模块的核心知识点两种线程创建方式继承Thread类、使用构造函数。线程同步用Lock、Condition等解决共享资源竞争。线程通信用Queue安全传递数据。实战场景生产者-消费者模型Condition实现。掌握threading模块后可进一步学习concurrent.futures.ThreadPoolExecutor线程池简化线程管理若需处理CPU密集型任务可学习multiprocessing模块多进程。建议结合实际需求编写代码例如“多线程下载文件”“多线程处理日志”在实践中加深对多线程的理解。下一篇咱们学习 Python入门Python3 asyncio模块全面学习教程附录扩展学习资源官方资源Python官网https://www.python.orgPyPIhttps://pypi.org查找第三方库安装包等相关文件另附带pycharm工具网盘下载地址https://pan.quark.cn/s/649af731037c学习资料视频和文档资源网盘下载地址 https://pan.quark.cn/s/ee16901a8954本专栏特色资源代码资源仓库CSDN专属资源在线获取联系博主xcLeigh 博主全栈领域优质创作者博客专家目前活跃在CSDN、微信公众号、小红书、知乎、掘金、快手、思否、微博、51CTO、B站、腾讯云开发者社区、阿里云开发者社区等平台全网拥有几十万的粉丝全网统一IP为xcLeigh。希望通过我的分享让大家能在喜悦的情况下收获到有用的知识。主要分享编程、开发工具、算法、技术学习心得等内容。很多读者评价他的文章简洁易懂尤其对于一些复杂的技术话题他能通过通俗的语言来解释帮助初学者更好地理解。博客通常也会涉及一些实践经验项目分享以及解决实际开发中遇到的问题。如果你是开发领域的初学者或者在学习一些新的编程语言或框架关注他的文章对你有很大帮助。亲爱的朋友无论前路如何漫长与崎岖都请怀揣梦想的火种因为在生活的广袤星空中总有一颗属于你的璀璨星辰在熠熠生辉静候你抵达。愿你在这纷繁世间能时常收获微小而确定的幸福如春日微风轻拂面庞所有的疲惫与烦恼都能被温柔以待内心永远充盈着安宁与慰藉。至此文章已至尾声而您的故事仍在续写不知您对文中所叙有何独特见解期待您在心中与我对话开启思想的新交流。 关注博主 带你实现畅游前后端 大屏可视化 带你体验酷炫大屏 神秘个人简介 带你体验不一样得介绍 从零到一学习Python 带你玩转Python技术流 前沿应用深度测评 前沿AI产品热门应用在线等你来发掘注本文撰写于CSDN平台,作者xcLeigh所有权归作者所有https://xcleigh.blog.csdn.net/如果相关下载没有跳转请查看这个地址相关链接没有跳转皆是抄袭本文转载请备注本文原地址。 亲码字不易动动小手欢迎点赞 ➕ 收藏如 问题请留言或者关注下方公众号看见后第一时间回复还有海量编程资料等你来领博主看见后一定及时给您答复