python进阶(七):并发和多线程

2023-11-18

一、多线程

image

并发是一种同时执行多个任务的方式,而多线程是一种实现并发的技术。在Python中,可以使用多线程来实现并发编程。了解Python的并发和多线程对于编写高效和响应性的程序非常重要。

并发 vs. 并行

在讨论并发和多线程之前,我们先来了解一下并发和并行的概念。虽然它们经常被混用,但它们有着不同的含义:

  • 并发(Concurrency):指多个任务交替执行的能力。这些任务可能在同一时间段内执行,但不一定是同时执行的。
  • 并行(Parallelism):指多个任务同时执行的能力。这些任务真正地同时执行,利用多个处理器或多核心来提高性能。

Python的多线程机制主要实现了并发,而不是真正的并行。这是因为Python的全局解释锁(Global Interpreter Lock,GIL)限制了同一时刻只能有一个线程执行Python字节码。

使用threading模块

Python的threading模块提供了多线程编程的支持。通过创建多个线程,可以并发执行多个任务。以下是一个简单的示例:

import threading

def task():
    print("Executing task")

# 创建线程
thread = threading.Thread(target=task)

# 启动线程
thread.start()

# 等待线程结束
thread.join()

print("Thread finished")

在上述示例中,我们定义了一个名为task的函数作为线程的执行体。然后,我们创建了一个线程对象thread,并指定了要执行的任务。通过调用start()方法启动线程,并使用join()方法等待线程结束。最后,我们在主线程中打印一条消息表示线程已经结束。

注意:

  • 使用threading模块可以创建多个线程,并并发执行多个任务。
  • start()方法用于启动线程,使其开始执行。
  • join()方法用于等待线程结束,以便在主线程中继续执行。

注意事项

在使用Python的多线程时,有几个注意事项需要记住:

  • 全局解释锁(GIL):Python的全局解释锁限制了同一时刻只能有一个线程执行Python字节码。这意味着在CPU密集型任务中,多线程并不能显著提高性能。但对于I/O密集型任务,多线程仍然可以提供一定的性能优势。
  • 竞态条件:多线程可能会引发竞态条件(Race Condition)问题。竞态条件发生在多个线程并发访问和修改共享数据时,导致结果无法预测或不一致。为了避免竞态条件,需要使用同步机制(如锁、信号量等)来保护共享数据的访问。
  • 死锁:死锁(Deadlock)是一种多线程编程中常见的问题。它发生在多个线程相互等待对方释放资源而无法继续执行的情况下。为了避免死锁,需要合理设计和管理线程的资源请求和释放。

当然,下面是关于Python线程池的详细说明:

二、线程池

线程池是一种管理和复用线程的机制,它可以提高多线程编程的效率和性能。在Python中,可以使用concurrent.futures模块提供的ThreadPoolExecutor来创建和管理线程池。

创建线程池

要创建一个线程池,可以使用concurrent.futures.ThreadPoolExecutor()构造函数。以下是一个简单的示例:

import concurrent.futures

# 创建线程池
with concurrent.futures.ThreadPoolExecutor() as executor:
    # 执行任务...

在上述示例中,我们使用with语句创建了一个线程池,并将其赋值给executor变量。通过ThreadPoolExecutor()构造函数创建的线程池默认具有适当数量的线程,可以根据需要进行扩展。

提交任务

要在线程池中执行任务,可以使用submit()方法提交任务。submit()方法接受一个可调用对象(如函数)作为参数,并返回一个Future对象,该对象代表任务的未来结果。以下是一个示例:

import concurrent.futures

def task(name):
    print(f"Executing task: {name}")

# 创建线程池
with concurrent.futures.ThreadPoolExecutor() as executor:
    # 提交任务给线程池
    future = executor.submit(task, "Task 1")

    # 获取任务的结果
    result = future.result()

在上述示例中,我们定义了一个名为task的函数,并将其作为任务提交给线程池。submit()方法返回一个Future对象,表示任务的未来结果。通过future.result()方法可以获取任务的结果。

批量提交任务

除了逐个提交任务,还可以使用map()方法批量提交任务。map()方法接受一个可调用对象和一个迭代器作为参数,并返回一个迭代器,该迭代器按顺序生成每个任务的结果。以下是一个示例:

import concurrent.futures

def task(name):
    print(f"Executing task: {name}")
    return f"Result of task: {name}"

# 创建线程池
with concurrent.futures.ThreadPoolExecutor() as executor:
    # 批量提交任务给线程池
    results = executor.map(task, ["Task 1", "Task 2", "Task 3"])

    # 获取任务的结果
    for result in results:
        print(result)

在上述示例中,我们定义了一个名为task的函数,并将其作为任务批量提交给线程池。通过executor.map()方法可以获取一个迭代器,按顺序生成每个任务的结果。通过遍历迭代器可以获取每个任务的结果。

注意:

  • 使用线程池可以方便地执行多个任务,并提高多线程编程的效率和性能。
  • 使用submit()方法可以逐个提交任务给线程池,并使用result()方法获取任务的结果。
  • 使用map()方法可以批量提交任务给线程池,并通过迭代器获取每个任务的结果。

控制并发度

线程池的并发度是指在同一时间内执行的线程数。默认情况下,线程池的并发度与系统的CPU核心数相同。但是可以通过设置ThreadPoolExecutormax_workers参数来控制并发度。以下是一个示例:

import concurrent.futures

# 设置并发度为2
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
    # 执行任务...

在上述示例中,我们通过将max_workers参数设置为2,将线程池的并发度限制为2个线程。这意味着在同一时间内最多只能有2个线程同时执行任务。

结束线程池

当不再需要线程池时,应该显式地关闭线程池以释放资源。可以使用shutdown()方法关闭线程池,它会等待所有线程执行完当前任务后再关闭线程池。以下是一个示例:

import concurrent.futures

# 创建线程池
with concurrent.futures.ThreadPoolExecutor() as executor:
    # 执行任务...

# 关闭线程池
executor.shutdown()

在上述示例中,我们使用with语句创建了一个线程池,并在代码块中执行任务。在with语句结束时,线程池会自动关闭。如果需要手动关闭线程池,可以调用shutdown()方法。

注意事项

在使用Python的线程池时,有几个注意事项需要记住:

  • 任务阻塞:如果任务之间存在依赖关系,可能会发生任务阻塞的情况。这可能导致线程池中的线程长时间等待,从而降低效率。为了避免任务阻塞,可以考虑使用异步编程技术,如asyncio模块。
  • 异常处理:任务在执行过程中可能会引发异常。为了避免线程池中的线程被异常终止,应该在任务函数内部进行适当的异常处理,并确保返回一个可识别的结果。
  • 资源管理:线程池中的线程共享一些资源(如数据库连接、文件句柄等),需要合理管理和释放这些资源,以避免资源泄漏或竞争条件。

结语

本文详细介绍了Python的并发和多线程。并发是一种同时执行多个任务的方式,而多线程是一种实现并发的技术。通过合理地使用多线程,你可以编写高效和响应性的程序。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python进阶(七):并发和多线程 的相关文章

随机推荐

  • Mysql 安装

    Mysql 安装 环境 windwos 10 1511 64bit mysql 5 7 14 一 下载mysql 1 在浏览器里打开mysql的官网http www mysql com 2 进入页面顶部的 Downloads 安卓培训 IT
  • Vite3 + Svelte3使用@import导入scss样式

    近年来 前端技术日新月异 Vite Vue3 Svelte SolidJS 等框架工具大放异彩 身为一个前端开发 总感觉一刻不学习就要out了 最近使用 Vite3 Svelte3 来构建封装自定义的 Web Components 开始了艰
  • 开发板配置NFS服务

    文章目录 NFS介绍 NFS版本 NFS服务器和客户端 安装NFS 配置NFS服务器 启动NFS服务 挂载NFS共享 NFS安全性 NFS日志 开发板配置NFS环境 环境 操作前先关闭防火墙 配置过程 server端的配置 开发板的操作 常
  • 华为OD机试真题 Java 实现【拔河比赛】【2023 B卷 100分】,附详细解题思路

    目录 专栏导读 一 题目描述 二 输入描述 三 输出描述 四 解题思路 五 Java算法源码 六 效果展示 1 输入 2 输出 3 说明 华为OD机试 2023B卷题库疯狂收录中 刷题点这里 专栏导读 本专栏收录于 华为OD机试 JAVA
  • JAVA--windows和linux下执行.class

    windows和linux下执行 class windows下执行 class linux下执行 class windows下执行 class title testJOb java cp jar com yang jobTest start
  • CMake命令

    1 aux source directory 查找当前目录所有源文件 并将源文件名称列表保存到DIR SRCS变量 不能查找子目录 aux source directory DIR SRCS 2 添加一个库或预编译库 添加一个库 名为
  • 企业实名认证接口

    详情链接 http www haoservice com docs 140 企业实名认证接口 通过营业执照全称 营业执照注册号 对公账户名 对公账号 清算联行号来验证信息一致不一致 支持格式 JSON XML 请求方式 GET POST 明
  • Springboot集成Redis——实现分布式锁

    目录 1 分布式锁 2 springboot集成redis 3 使用setnx命令实现分布式锁 4 使用Redission实现分布式锁 5 redission分布式锁的类型 1 分布式锁 分布式锁 即分布式系统中的锁 随着业务发展的需要 原
  • Android App的工作原理

    Android App的工作原理 Android系统是基于liunx内核的 但是与传统的基于liunx的pc系统不同 用户对Android app没有绝对的掌控权 pc系统中 在应用程序的系统菜单上选择 退出 或者 关闭 之类的选项会直接杀
  • 大型项目一定用angular吗

    不一定 虽然Angular在构建大型项目方面具有优势 但选择使用何种前端框架还需要考虑多个因素 包括项目需求 团队技能 开发周期 项目规模和性能需求等 以下是一些需要考虑的因素 项目规模和复杂性 Angular 的模块化 依赖注入和组件化架
  • bootstrap label的for属性

  • Spring Boot 统一返回前端封装VO类型结果集定义

    现在大部分项目都是前后端分离的项目 为了统一管理 后端需要对数据进行封装对应的VO数据 什么是Vo我就不叙述了 这里贴出我自己的VO封装类 项目的故障码并没有定义太多 所以也没有定义枚举类型 供大家参考 import io swagger
  • Unity查看接入的Ironsource和adapter 版本号

    APPLOVINADAPTER版本号
  • vmware 开机自动启动虚拟机

    vmware开机自动启动 可以使用vmrun命令 1 首先在 我的电脑 属性 高级 环境变量 PATH 中添加vmware路径 如 C Program Files x86 VMware VMware Workstation 2 新建一个 启
  • Kafka一文懂

    初识 Kafka 什么是 Kafka Kafka 是由 Linkedin 公司开发的 它是一个分布式的 支持多分区 多副本 基于 Zookeeper 的分布式消息流平台 它同时也是一款开源的基于发布订阅模式的消息引擎系统 Kafka 的基本
  • 影响DDR5稳定性的RAS功能

    内存的稳定性 离不开RAS功能 这里的RAS Reliability Availability and Serviceability 即可靠性 可用性和可维护性的简称 RAS功能一方面可以通过调整信号规避风险 另一方面 在发生错误时及时发现
  • js常用正则表达式 匹配多个汉字、数字、英文、所有字符(附带Layui中form的表单验证)

    常用正则表达式 转自 菜鸟工具 https c runoob com front end 854 一 校验数字的表达式 数字 0 9 n位的数字 d n 至少n位的数字 d n m n位的数字 d m n 零和非零开头的数字 0 1 9 0
  • 系统部署的基本流程

    系统部署的基本流程 系统升级部署的步骤 系统升级部署的步骤 一 web后台 1 确保代码正确 配置正确 打包为war 2 登录现有web端查看部分数据正常 数据库部分表时间段数据正常 3 连接服务器 进入相应tomcat 停止tomcat
  • Vite简介

    Vite是一个快速 轻量级的前端构建工具 它可以让开发者更高效地进行前端开发 相比于其他构建工具 Vite的特点在于快速的冷启动 模块热替换和按需编译等功能 下面我们将详细探讨Vite的优势和如何使用它 什么是Vite Vite是一款基于R
  • python进阶(七):并发和多线程

    一 多线程 原文 大纲 首页 并发是一种同时执行多个任务的方式 而多线程是一种实现并发的技术 在Python中 可以使用多线程来实现并发编程 了解Python的并发和多线程对于编写高效和响应性的程序非常重要 并发 vs 并行 在讨论并发和多