Python多线程编程之线程间通信实践

 更新时间:2026年06月13日 16:10:12   作者:小宇不内向  
这段文章详细介绍了Python线程间通信的两种方法:共享变量和Queue队列,文章解释了Queue中的`join()`与`task_done()`方法的作用,并澄清了一些常见的误解,强调了正确使用这些方法的重要性

python线程间通信,有两种常用的方法:

1. 共享变量

定义一个全局变量,然后在不同的线程函数中,使用 global 关键字声明为全局变量:

detail_url_list = []    # 全局变量
def get_detail_html():
    # 爬取文章详情页
    global detail_url_list    # 用 global 声明为全局变量
    while True:
        if len(detail_url_list):
            url = detail_url_list.pop()
            # for url in detail_url_list:
            print("get detail html started")
            time.sleep(2)
            print("get detail html end")
def get_detail_url():
    global detail_url_list    # 用 global 声明为全局变量
    while True:
        # 爬取文章列表页
        print("get url started")
        time.sleep(2)
        for i in range(20):
            detail_url_list.append("http://projectstedu.com/{id}".format(id=i))
        print("get detail url end")

共享变量方法要考虑到线程间安全性。

2. 通过 Queue 的方式进行线程间同步

from queue import Queue

Queue 本身就是线程安全的。

from queue import Queue
import time
import threading
def get_detail_html(queue):
    # 爬取文章详情页
    while True:
        url = queue.get()
        # for url in detail_url_list:
        print("get detail html started")
        time.sleep(2)
        print("get detail html end")
def get_detail_url(queue):
    # 爬取文章列表页
    while True:
        print("get detail url started")
        time.sleep(4)
        for i in range(20):
            queue.put("http://projectsedu.com/{id}".format(id=i))
        print("get detail url end")
detail_url_queue = Queue(maxsize=1000)    # 设置 Queue的最大数
thread_detail_url = threading.Thread(target=get_detail_url, args=(detail_url_queue,))
thread_detail_url.start()
for i in range(10):    # 启动10条线程
    html_thread = threading.Thread(target=get_detail_html, args=(detail_url_queue,))
    html_thread.start()
detail_url_queue.task_done()
detail_url_queue.join()

理解 Queue 队列中 join() 与 task_done() 的关系。

看了网上的文章,一般是这样说的:

  • 如果线程里每从队列里取一次,但没有执行 task_done(),则 join 无法判断队列到底有没有结束,在最后执行个 join() 是等不到结果的,会一直挂起。
  • 可以理解为,每 task_done() 一次 就从队列里删掉一个元素,这样在最后 join 的时候根据队列长度是否为零来判断队列是否结束,从而执行主线程。

自己的理解:

  • task_done() 给了 join()信号,告诉 join() 取出了一个元素,join() 就会判断队列长度是否为零了,如果为零,则结束线程,停止阻塞,回到主线程。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 详解PyTorch nn.Embedding() 嵌入

    详解PyTorch nn.Embedding() 嵌入

    在自然语言处理(NLP)中,将文本序列转化为数字序列(tokenid)后,为了使模型能更好地理解这些数字背后的含义,引入了嵌入层(Embedding)通过简单的示例,可以看出Embedding的获取过程及其在理解语言中的关键作用
    2024-11-11
  • python cv2 安装步骤详解

    python cv2 安装步骤详解

    文章介绍了Python中安装OpenCV的两种方法pip和conda,涵盖不同版本(含GPU/额外模块)的安装命令,以及验证安装和注意事项(如更新工具、权限处理、推荐使用虚拟环境),感兴趣的朋友一起看看吧
    2025-07-07
  • python实现代码行数统计示例分享

    python实现代码行数统计示例分享

    这篇文章主要介绍了python实现代码行数统计的示例,需要的朋友可以参考下
    2014-02-02
  • 解决python3 urllib 链接中有中文的问题

    解决python3 urllib 链接中有中文的问题

    今天小编就为大家分享一篇解决python3 urllib 链接中有中文的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • python模拟登陆、POST/GET请求方式

    python模拟登陆、POST/GET请求方式

    这篇文章主要介绍了python模拟登陆、POST/GET请求方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • Python OpenCV 图像平移的实现示例

    Python OpenCV 图像平移的实现示例

    本篇博客学习OpenCV 中关于图像平移的方法,核心学习到的方法是warpAffine,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • python、Matlab求定积分的实现

    python、Matlab求定积分的实现

    今天小编就为大家分享一篇python、Matlab求定积分的实现,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • Pycharm保存不能自动同步到远程服务器的解决方法

    Pycharm保存不能自动同步到远程服务器的解决方法

    今天小编就为大家分享一篇Pycharm保存不能自动同步到远程服务器的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-06-06
  • Python操作MongoDB数据库PyMongo库使用方法

    Python操作MongoDB数据库PyMongo库使用方法

    这篇文章主要介绍了Python操作MongoDB数据库PyMongo库使用方法,本文讲解了创建连接、连接数据库、连接聚集、查看全部聚集名称、查看聚集的一条记录等操作方法,需要的朋友可以参考下
    2015-04-04
  • Python使用everything库构建文件搜索和管理工具

    Python使用everything库构建文件搜索和管理工具

    在这篇博客中,我将分享如何使用 Python 的 everytools库构建一个简单的文件搜索和管理工具,这个工具允许用户搜索文件、查看文件路径、导出文件信息到 Excel,以及生成配置文件,文中有相关的代码示例供大家参考,需要的朋友可以参考下
    2024-08-08

最新评论