Python多任务编程

news2025/7/8 14:17:39

1.进程与多任务

1. 1 多任务的介绍

1.使用多任务能充分利用CPU资源,提高程序的执行效率,让程序具备处理多任务的能力。

2.多任务执行方式有两种:

并发:在一段时间内交替执行多个任务。

并行:在一段时间内真正的同时一起执行多个任务。

1.2 进程的介绍

1.进程(Process)是资源分配的最小单位

2.多进程是Python程序中实现多任务的一种方式,使用多进程可以大大提高程序的执行效率。

1.3 多进程完成多任务

1.导入进程包。

2.创建子进程并指定执行的任务。

3.启动进程执行任务。

# 导入进程模块
import multiprocessing
import time

# 敲代码
def coding():
    for i in range(3):
        print("coding...")
        time.sleep(0.2)

# 听音乐
def music():
    for i in range(3):
        print("music...")
        time.sleep(0.2)

if __name__ == '__main__':
    # coding()
    # music()
    # 通过进程类创建进程对象
    coding_process = multiprocessing.Process(target=coding)
    music_process = multiprocessing.Process(target=music)
    # 启动进程
    coding_process.start()
    music_process.start()

1.4 进程执行带有参数的任务

进程执行带有参数的任务有两种方式:

1.元组方式传参:元组方式传参一定要和参数的顺序保持一致。

2.字典方式传参:字典方式传参字典中的key一定要和参数名保持一致。

# 导入进程模块
import multiprocessing
import time

# 敲代码
def coding(num,name):
    for i in range(num):
        print(name)
        print("coding...")
        time.sleep(0.2)

# 听音乐
def music(count):
    for i in range(count):
        print("music...")
        time.sleep(0.2)

if __name__ == '__main__':
    # coding()
    # music()
    # 通过进程类创建进程对象
    coding_process = multiprocessing.Process(target=coding,args=(3,"zs"))
    music_process = multiprocessing.Process(target=music,kwargs={"count":2})
    # 启动进程
    coding_process.start()
    music_process.start()

1.5 获取进程编号

1.获取当前进程编号

os.getpid()

2.获取当前父进程编号

os.getppid()

# 导入进程模块
import multiprocessing
import os
import time

# 敲代码
def coding():
    # 获取coding_process的编号
    print("coding_process>>>%d" % os.getpid())
    # 获取coding_process的父进程的编号
    print("coding_process的父进程>>>%d" % os.getppid())
    for i in range(3):
        print("coding...")
        time.sleep(0.2)

# 听音乐
def music():
    # 获取music_process的编号
    print("music_process>>>%d" % os.getpid())
    # 获取music_process的父进程的编号
    print("music_process的父进程>>>%d" % os.getppid())
    for i in range(3):
        print("music...")
        time.sleep(0.2)

if __name__ == '__main__':
    # 获取主进程的编号
    print("主进程>>>%d" % os.getpid())
    # 通过进程类创建进程对象
    coding_process = multiprocessing.Process(target=coding)
    music_process = multiprocessing.Process(target=music)
    # 启动进程
    coding_process.start()
    music_process.start()

两个子进程的父进程的编号与主进程的编号相同,证明两个子进程是由该父进程创建并启动的。

1.6 进程间不共享全局变量

  • 创建子进程会对主进程资源进行拷贝,也就是子进程就是主进程的一个副本。
  • 进程间不共享全局变量,因为操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已。
import multiprocessing
import time

# 全局变量
my_list = []

# 写入数据
def write_data():
    for i in range(3):
        my_list.append(i)
        print("add:",i)
    print("write_data:",my_list)

# 读取数据
def read_data():
    print("read_data:",my_list)

if __name__ == '__main__':
    # 创建写入数据进程
    write_process = multiprocessing.Process(target=write_data)
    # 创建读取数据进程
    read_process = multiprocessing.Process(target=read_data)

    # 启动进程,执行任务
    write_process.start()
    time.sleep(1)
    read_process.start()

写入数据进程和读取数据进程不共享my_list这个全局变量。 

1.7 主进程和子进程的结束顺序

默认情况下,为了保证子进程能够正常的运行,主进程会等待所有的子进程执行完后再结束。

如果想要让主进程结束后子进程就销毁,可以采取以下两种方式:

  • 设置守护主进程方式:子进程对象.daemon = True
  • 销毁子进程方式:子进程对象.terminate()
import multiprocessing
import time

# 工作函数
def work():
    for i in range(10):
        print("工作中...")
        time.sleep(0.2)

if __name__ == '__main__':
    # 创建子进程
    work_process = multiprocessing.Process(target=work)

    # # 方式一:设置守护主进程
    # work_process.daemon = True

    # 启动子进程
    work_process.start()

    # 延时1秒
    time.sleep(1)

    # 方式二:手动销毁子进程
    work_process.terminate()

    print("主进程执行完毕")

2. 线程与多任务

2.1 线程的介绍

1.多线程是Python程序中实现多任务的一种方式。

2.线程是程序执行的最小单位

3.同属一个进程的多个线程共享进程所拥有的全部资源

2.2 多线程完成多任务

1.导入线程模块

2.创建子线程

3.启动线程执行任务

import time
import threading

# 敲代码
def coding():
    for i in range(3):
        print("coding...")
        time.sleep(0.2)

# 听音乐
def music():
    for i in range(3):
        print("music...")
        time.sleep(0.2)

if __name__ == '__main__':
    # 创建子线程
    coding_thread = threading.Thread(target=coding)
    music_thread = threading.Thread(target=music)
    # 启动线程执行任务
    coding_thread.start()
    music_thread.start()

2.3 线程执行带有参数的任务

线程执行带有参数的任务有两种方式:

1.元组方式传参:元组方式传参一定要和参数的顺序保持一致。

2.字典方式传参:字典方式传参字典中的key一定要和参数名保持一致。

import time
import threading

# 敲代码
def coding(num):
    for i in range(num):
        print("coding...")
        time.sleep(0.2)

# 听音乐
def music(count):
    for i in range(count):
        print("music...")
        time.sleep(0.2)

if __name__ == '__main__':
    # 创建子线程
    coding_thread = threading.Thread(target=coding,args=(3,))
    music_thread = threading.Thread(target=music,kwargs={"count" : 2})
    # 启动线程执行任务
    coding_thread.start()
    music_thread.start()

2.4 主线程和子线程的结束顺序

默认情况下,为了保证子线程够正常的运行,主线程会等待所有的子线程执行完后再结束。

如果想要让主线程结束后子线程就销毁,可以采取以下两种方式:

  • 方式一:参数方式设置守护主线程
  • 方式二:方法方式设置守护主线程
import time
import threading

# 工作函数
def work():
    for i in range(10):
        print("work...")
        time.sleep(0.2)

if __name__ == '__main__':
    # 创建线程
    # 方式一:参数方式设置守护主线程
    # work_thread = threading.Thread(target=work,daemon=True)
    work_thread = threading.Thread(target=work)

    # 方式二:方法方式设置守护主线程
    work_thread.setDaemon(True)

    # 启动线程执行任务
    work_thread.start()

    # 延时1秒
    time.sleep(1)
    print("主线程执行完毕")

2.5 线程间的执行顺序

 线程之间执行是无序的,是由CPU调度决定某个线程先执行的。

import threading
import time

# 获取线程信息函数
def get_info():
    time.sleep(0.5)
    # 获取线程信息
    current_thread = threading.current_thread()
    print(current_thread)

if __name__ == '__main__':
    for i in range(10):
        # 创建子线程
        sub_thread = threading.Thread(target=get_info)
        # 启动线程执行任务
        sub_thread.start()

2.6 线程间共享全局变量

import threading
import time

# 全局变量
my_list = []

# 写入数据
def write_data():
    for i in range(3):
        my_list.append(i)
        print("add:",i)
    print("write_data:",my_list)

# 读取数据
def read_data():
    print("read_data:",my_list)

if __name__ == '__main__':
    # 创建写入数据线程
    write_thread = threading.Thread(target=write_data)
    # 创建读取数据线程
    read_thread = threading.Thread(target=read_data)

    # 启动线程,执行任务
    write_thread.start()
    time.sleep(1)
    read_thread.start()

线程间共享my_list这个共享变量。

2.7 线程间资源竞争问题

多线程同时操作全局变量可能会导致数据出现错误,可以使用线程同步方式来解决这个问题。

线程同步方式:

  • 互斥锁
import threading

# 全局变量
g_num = 0

# 对g_num进行加操作
def sum_num1():
    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1
    print("g_num1:",g_num)

# 对g_num进行加操作
def sum_num2():
    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1
    print("g_num2:",g_num)

if __name__ == '__main__':
    # 创建子线程
    sum1_thread = threading.Thread(target=sum_num1)
    sum2_thread = threading.Thread(target=sum_num2)

    # 启动线程
    sum1_thread.start()
    sum2_thread.start()

2.8 互斥锁的使用

1.互斥锁的使用

threading.Lock()

2.上锁

mutex.acquire()

3.解锁

mutex.release()

import threading

# 全局变量
g_num = 0

# 对g_num进行加操作
def sum_num1():
    # 上锁
    mutex.acquire()

    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1

    # 解锁
    mutex.release()

    print("g_num1:",g_num)



# 对g_num进行加操作
def sum_num2():
    # 上锁
    mutex.acquire()
    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1

    # 解锁
    mutex.release()

    print("g_num2:",g_num)


if __name__ == '__main__':
    # 互斥锁的创建
    mutex = threading.Lock()

    # 创建子线程
    sum1_thread = threading.Thread(target=sum_num1)
    sum2_thread = threading.Thread(target=sum_num2)

    # 启动线程
    sum1_thread.start()
    sum2_thread.start()

 

2.9 死锁

死锁:一直等待对方释放锁的情景就是死锁。

死锁的结果:会造成应用程序停止响应,不能再处理其它任务了。

死锁的注意点:

  • 使用互斥锁的时候需要注意死锁的问题,在合适的地方注意释放锁。
  • 死锁一旦产生就会造成应用程序的停止响应,应用程序无法继续往下执行了。
import threading

# 全局变量
g_num = 0

# 对g_num进行加操作
def sum_num1():
    print("sum_num1...")

    # 上锁
    mutex.acquire()

    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1

    print("g_num1:",g_num)


# 对g_num进行加操作
def sum_num2():
    print("sum_num2...")

    # 上锁
    mutex.acquire()
    for i in range(1000000):
        # 声明全局变量
        global g_num
        g_num += 1

    print("g_num2:",g_num)


if __name__ == '__main__':
    # 互斥锁的创建
    mutex = threading.Lock()

    # 创建子线程
    sum1_thread = threading.Thread(target=sum_num1)
    sum2_thread = threading.Thread(target=sum_num2)

    # 启动线程
    sum1_thread.start()
    sum2_thread.start()

线程sum1_thread占用锁资源,而线程sum2_thread请求锁资源,导致死锁,线程无法继续运行下去。

2.10 进程和线程的对比

2.10.1 关系对比

线程是依附在进程里面的,没有进程就没有线程。

一个进程默认提供一条线程,当然进程可以创建多个线程。

2.10.2 区别对比

进程之间不共享全局变量,而线程之间共享全局变量(但是要注意资源竞争的问题)。

创建进程的资源开销大于线程。

进程是OS资源分配的基本单位,线程是CPU调度的基本单位。

线程不能独立执行,必须依存在进程中。

2.10.3 优缺点

1.进程优缺点:

优点:可以用多核(多个进程并行执行)。

缺点:资源开销大。

2.线程优缺点:

优点:资源开销小。

缺点:只能使用单核(多个线程并发执行)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/18348.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第三周 青海之行——练练构图,培养你的摄影眼

目录3.1 油菜花海,怎么拍更好看?3.2 构图的元素:线条、形状、图案(一)3.3 构图的元素:光影、留白、框景(二)3.4 摄影构图 补充内容构图作业3.1 油菜花海,怎么拍更好看? 祁连山下的百里油菜花海 门源 雪山下…

冲冲冲!!!python计算机二级每日一套_8

文章目录一、选择题二、基本操作三、简单应用四、综合应用声明:例题均来源于网络,仅供学习笔记,若涉侵权请联系删除。所属练题来源于《小黑课堂》一、选择题 1、树的度为3,共有31个结点,但没有度为1和2的结点。则该树…

C++ Reference: Standard C++ Library reference: Containers: deque: deque: clear

C官网参考链接&#xff1a;https://cplusplus.com/reference/deque/deque/clear/ 公有成员函数 <deque> std::deque::clear C98 void clear(); C11 void clear() noexcept;清除内容 从deque中删除所有元素&#xff08;已销毁&#xff09;&#xff0c;使容器的size为0。…

MBIST BAP(Bist Access Port)直接访问接口(1)

More articles You can follow the official account&#xff1a;“IC练习生” IC民工不定期更新 BAP BAP会覆盖掉连接到BAP上的memory的一些默认操作模式; 通过消除串行配置控制器的shift cycle,大大缩短测试时间,代价是在BAP和控制器之间额外的连接; BAP的高级访问属性部分…

【渝偲】DSPE-PEG-Mannose磷脂聚乙二醇甘露糖;科研试剂

DSPE-PEG-Mannose磷脂聚乙二醇甘露糖 DSPE-PEG-Mannose 磷脂聚乙二醇甘露糖 英文名称:DSPE-PEG-Mannose 中文名称:磷脂聚乙二醇甘露糖 结构式&#xff1a; 性状: PEG2000分子量为白色粉末溶剂:溶于大部分有机溶剂&#xff0c;如&#xff1a;DCM、DMF、DMSO、THF等等。在水中…

【Linux进程间通信】 管道

这里写目录标题管道有名管道无名管道在使用无名管道时为什么要关闭不使用的另外一端&#xff1f;IPC机制&#xff1a;管道&#xff0c;信号量&#xff0c;共享队列&#xff0c;消息队列&#xff0c; 套接字。 管道&#xff0c;信号量&#xff0c;共享队列&#xff0c;消息队列…

[附源码]SSM计算机毕业设计中青年健康管理监测系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Design A Pastebin

title: Notes of System Design No.03 — Design a PasteBin description: Design a PasteBin ’ date: 2022-05-13 18:01:58 tags: 系统设计 categories: 系统设计 00. What is Pastebin? 这是一个网站 在输入框输入文本 网站上会生成一个URL链接 别人可以通过这个链接 …

【图神经网络论文整理】(一)—— 可解释性和泛化性图分类的因果注意力:CAL

KDD 22: Proceedings of the 28th ACM SIGKDD Conference on Knowledge Discovery and Data MiningAugust 2022Pages 1696–1705论文地址 本文介绍的论文是中科大王翔教授等人在KDD2022上发表的《Causal Attention for Interpretable and Generalizable Graph Classification》…

【数据处理】Python matplotlib绘制双柱状图以及绘制堆积柱状图——保姆级教程

Python matplotlib绘制双柱状图以及绘制堆积柱状图双柱状图一、双柱状图的原理二、双柱状图的完善1. 增加图片标题2. 增加x轴y轴标题3. 增加x轴注释四、完整代码堆积柱状图一、堆积柱状图的绘制原理二、plt.bar参数介绍三、完整代码&#xff1a;双柱状图 一、双柱状图的原理 …

机器人C++库(12)Robotics Library 之指定路径规划算法

机器人C库&#xff08;12&#xff09;Robotics Library 之路径规划算法&#xff1a;PRM、RRT、EET算法 RL库的运动规划(rl::plan)模块集成了以下经典的路径规划算法&#xff1a; PRM算法:概率路线图算法RRT算法&#xff1a;快速探索随机树算法EET算法&#xff1a;搜索树算法-基…

java计算机毕业设计ssm基金分析系统的设计与实现

项目介绍 计算机信息技术的发展,推动了基金信息化管理的进程,并随着互联网&#xff1a;概念的提出,各种互联网&#xff1a;软件也应运而生。在传统的管理中,各种信息管理难,传播速度慢,需要耗费很长时间统计核查,不能满足现代化的发展需求,基于JAVA的基金分析系统的提出解决了…

python+django家政服务中介网站系统

通常 一个Django model 对应一张数据表&#xff0c;model是以类的形式表现的 实现了ORM 对象与数据库映射 隐藏了数据访问细节 不需要写sql语句 admin是Django自带的 自动化数据管理界面 前端技术&#xff1a;nodejsvueelementui 我们最初的项目结构由五个文件组成&#xf…

《树莓派项目实战》第六节 使用超声波模块测距

目录 6.1 引脚介绍 6.2 工作原理 6.3 使用注意 6.4 连接到树莓派 6.5 编写代码输出距离 在本节&#xff0c;我们将学习如何使用HC-SR04超声波模块测量前方障碍物的距离&#xff0c;该项目设计到的材料有&#xff1a; 树莓派 * 1面包板 * 1杜邦线若干HC-SR04超声波模块* 1…

Mysql进阶之索引与视图和三大范式

1、索引&#xff08;index&#xff09; 1.1、什么是索引&#xff1f; 索引是在数据库表的字段上添加的&#xff0c;是为了提高查询效率存在的一种机制。 一张表的一个字段可以添加一个索引&#xff0c;当然&#xff0c;多个字段联合起来也可以添加索引。 索引相当于一本书的…

redis搭建主从、redis搭建集群、redis中StrictRedis()、RedisCluster()方法与python交互

一、StrictRedis方法 创建对象&#xff0c;指定host、port、db与指定的服务器端口连接&#xff0c;其中默认host为localhost、port为6379、db为0&#xff0c;不同类型调用的实例方法不同&#xff0c;与redis命令一致&#xff0c;方法需要的参数与命令参数一致 from redis imp…

Xavier(8):Xavier使用速腾聚创激光雷达运行a-loam算法部分报错与解决方案

文章目录1 速腾聚创激光雷达驱动报错&#xff1a;Project cv_bridge specifies /usr/include/opencv as an include dirProject grid_map_cv specifies /usr/include/opencv as an include dir2 a-loam算法报错&#xff1a; fatal error: opencv/cv.h: 没有那个文件或目录报错&…

无线社工基础

无线社工基础 一些社会工程学密码生成器&#xff08;百度&#xff09; Crunch工具 /usr/share/crunch/charset.lstcrunch 最短长度 最长长度 字符集 选项crunch 8 12 -f /usr/share/crunch/charset.lst ualpha -o /root/pass.txt Windows下对附近无线网络进行扫描 WirelessMon…

MySQL事务/事务与数据库底层数据/多点回滚/隔离级别/悲观锁和乐观锁/锁模式和分类/相关锁总结/JDBC事务实现

文章目录MySQL事务概述事务事务与数据库底层数据事务控制语句事务处理基本测试多点回滚相关日志问题redo logundo log隔离级别常见问题事务隔离性隔离级别的范围总结隔离等级读未提交读已提交可重复读串行化并发写问题幻读问题悲观锁和乐观锁锁模式锁分类按加锁方式分类按照算法…

基于贝叶斯推理估计稳态 (ST) 和非稳态 (NS) LPIII 模型分布拟合到峰值放电(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…