(python篇) 多进程与多线程

news/2024/3/4 9:51:51

一、多任务

  • 并发与并行

    • 并发

      CPU调度执行速度太快了,看上去一起执行,任务数多于CPU核心数

    • 并行

      真正一起执行,任务数小于等于CPU核心数

    • 并发是逻辑上的同时发生,并行更多是侧重于物理上的同时发生。

  • 实现多任务的方式

    • 多进程模式

      启动多个进程,每个进程虽然只有一个线程,但是多个进程可以一起执行多个任务

    • 多线程模式

      启动一个进程,在一个进程的内部启动多个线程,这样多个线程也可以一起执行多个任务

    • 多进程+多线程

      启动多个进程,每个进程再启动多个线程

    • 协程

    • 多进程+协程

二、进程

1、使用进程

  • 启动进程实现多任务

    • multiprocessing模块

      跨平台的多进程模块,提供了一个Process类用来实例化一个进程对象

    • Process类

      作用:创建进程(子进程)

    • __name__

      这是 Windows 上多进程的实现问题。在 Windows 上,子进程会自动 import 启动它的这个文件,而在 import 的时候是会执行这些语句的。如果你这么写的话就会无限递归创建子进程报错。所以必须把创建子进程的部分用那个 if 判断保护起来,import 的时候 __name__ 不是 __main__ ,就不会递归运行了。

      参数说明
      target指定进程执行的任务
      args给进程函数传递的参数,是一个元组

      注意:此时进程被创建,但是不会启动进程执行

    • 启动进程实现多任务

      from multiprocessing import Process

      创建子进程

 import timefrom multiprocessing import Processdef run1():for i in range(7):print("lucky is a good man")time.sleep(1)def run2(name, word):for i in range(5):print("%s is a %s man"%(name, word))time.sleep(1)if __name__ == "__main__":t1 = time.time()'''P = Process(target=run,args=("nice",),name='当前进程名称')target指定 子进程运行的函数args 指定传递的参数 , 是元组类型启动进程:Process对象.start()'''p1 = Process(target=run1)p2 = Process(target=run2, args=("lucky", "cool"))p1.start()p2.start()# 主进程的结束不能影响子进程,所以可以等待子进程的结束再结束主进程# 等待子进程结束,才能继续运行主进程p1.join()p2.join()t2 = time.time()print("耗时:%.2f"%(t2-t1))
**获取进程信息**+ os.getpid()	 获取当前进程id号
+ os.getppid() 获取当前进程的父进程id号
+ multiprocessing.current_process().name   获取当前进程名称**父子进程的先后顺序**+ 默认   父进程的结束不能影响子进程  让父进程等待子进程结束再执行父进程+ p.join()  阻塞当前进程,直到调用join方法的那个进程执行完,再继续执行当前进程。+ 全局变量在过个进程中不能共享**注意:** 在子线程中修改全局变量时对父进程中的全局变量没有影响

2、全局变量在多个子进程中不能共享

原因:

​ 在创建子进程时对全局变量做了一个备份,父进程中num变量与子线程中的num不是一个变量

3、启动大量子进程

from multiprocessing import Pool
import timedef fun1(name):print(f'我是{name}开始')time.sleep(3)print(f'我是{name}结束')if __name__ == '__main__':print('CPU number:' + str(multiprocessing.cpu_count())) # 获取CPU核心数p = Pool(2)             # 开启并发数,实例化进程池  默认为核心数for i in range(1, 11):  # 创建了10个进程p.apply_async(fun1, args=(i, ))  # 把任务添加到进程池p.close()  # 关闭进程池p.join()  # 进程池等待'''调用join之前必须先调用close调用close之后就不能再继续添加新的进程进程池对象调用join,会等待进程池中所有的子进程结束完毕再去执行父进程'''

4、map方法

from multiprocessing import Pool
import timedef fun1(name):print(f'我是{name}开始')time.sleep(3)print(f'我是{name}结束')if __name__ == '__main__':p = Pool(2)  # 实例化进程池  默认为核心数t_list = list(range(1, 11))  # 传递进去的参数 1-10# print(t_list)p.map(fun1, t_list)  # 任务添加到进程池

5、进程间通信

队列

  • 队列常用函数

    Queue.empty() 如果队列为空,返回True, 反之False

    Queue.full() 如果队列满了,返回True,反之False

    Queue.get([block[, timeout]]) 获取队列,timeout等待时间

    Queue.get_nowait() 相当Queue.get(False)

    Queue.put(item) 阻塞式写入队列,timeout等待时间

    Queue.put_nowait(item) 相当Queue.put(item, False)

  • 特点:先进先出

  • 注意:

    get方法有两个参数,blocked和timeout,意思为阻塞和超时时间。默认blocked是true,即阻塞式。

    当一个队列为空的时候如果再用get取则会阻塞,所以这时候就需要吧blocked设置为false,即非阻塞式,实际上它就会调用get_nowait()方法,此时还需要设置一个超时时间,在这么长的时间内还没有取到队列元素,那就抛出Queue.Empty异常。

    当一个队列为满的时候如果再用put放则会阻塞,所以这时候就需要吧blocked设置为false,即非阻塞式,实际上它就会调用put_nowait()方法,此时还需要设置一个超时时间,在这么长的时间内还没有放进去元素,那就抛出Queue.Full异常。

  • 队列的大小

    Queue.qsize() 返回队列的大小 ,不过在 Mac OS 上没法运行。

from multiprocessing import Process, Queuedef test(q):# 子进程放入数据q.put('a')q.put('b')q.put('c')if __name__ == '__main__':q = Queue()   #创建队列p = Process(target=test, args=(q, ))p.start()p.join()print(q.get())  # 主进程拿数据print(q.get())  # 主进程拿数据print(q.get())  # 主进程拿数据print(q.get(timeout=3))  # 主进程拿数据

字典共享
Manager是一个进程间高级通信的方法 支持Python的字典和列表的数据类型

from multiprocessing import Process, Managerdef test(d):d['name'] = 'lucky'd['sex'] = 'man'if __name__ == '__main__':p_dict = Manager().dict()  # 创建了进程通信的字典类型p = Process(target=test, args=(p_dict, ))p.start()p.join()print(p_dict)  # {'name': 'lucky', 'sex': 'man'}

列表共享

from multiprocessing import Process, Managerdef test(l):l.append('a')l.append('b')l.append('c')if __name__ == '__main__':p_list = Manager().list()p = Process(target=test, args=(p_list, ))p.start()p.join()print(p_list)  # ['a', 'b', 'c']
  • deamon
 import multiprocessingimport timedef fun():time.sleep(100)if __name__=='__main__':p = multiprocessing.Process(target=fun)# 设置在start()方法之前,设置为True,当父进程结束后,子进程会自动被终止p.daemon = True p.start()
  • 进程名.terminate() 强行终止子进程
 import multiprocessingimport timedef fun():time.sleep(100)if __name__=='__main__':p = multiprocessing.Process(target=fun)p.start()p.terminate()p.join()

6、进程实现生产者消费者

生产者消费者模型描述:

生产者是指生产数据的任务,消费者是指消费数据的任务。

当生产者的生产能力远大于消费者的消费能力,生产者就需要等消费者消费完才能继续生产新的数据,同理,如果消费者的消费能力远大于生产者的生产能力,消费者就需要等生产者生产完数据才能继续消费,这种等待会造成效率的低下,为了解决这种问题就引入了生产者消费者模型。

即:两个或者更多的进程(线程)共享同一个缓冲区,其中一个或多个进程(线程)作为“生产者”会不断地向缓冲区中添加数据,另一个或者多个进程(线程)作为“消费者”从缓冲区中取走数据。

from multiprocessing import Process
from multiprocessing import Queue
import timedef product(q):print("启动生产子进程……")for data in ["good", "nice", "cool", "handsome"]:time.sleep(2)print("生产出:%s"%data)# 将生产的数据写入队列q.put(data)print("结束生产子进程……")def customer(q):print("启动消费子进程……")while 1:print("等待生产者生产数据")# 获取生产者生产的数据,如果队列中没有数据会阻塞,等待队列中有数据再获取value = q.get()print("消费者消费了%s数据"%(value))print("结束消费子进程……")if __name__ == "__main__":q = Queue()p1 = Process(target=product, args=(q,))p2 = Process(target=customer, args=(q,))p1.start()p2.start()p1.join()# p2子进程里面是死循环,无法等待它的结束# p2.join()# 强制结束子进程p2.terminate()

三、线程

1、threading模块

import threading
import timedef run():# 获取当前线程名称  默认名称Thread-1print(threading.current_thread().name)print('run函数开始')time.sleep(3)print('run函数结束')if __name__ == '__main__':th = threading.Thread(target=run, name='lucky-1')th.start()th.join()  # 阻塞等待  和进程一样的print('over')# 查看主线程名称print(threading.main_thread().name)

2、多线程

import threading
import timedef run(i):print('子线程开始', threading.current_thread().name)print(f'{i}开始干活')time.sleep(3)print(f'{i}干活结束')if __name__ == '__main__':t1 = time.time()t_list = []   # 存储线程对象# 并发执行5个线程for i in range(1, 6):thr = threading.Thread(target=run, args=(i, ))t_list.append(thr) # 线程对象添加到列表中# 循环开启子线程for t in t_list:t.start()# 循环阻塞子线程for i in t_list:i.join()# 打印执行时间print(time.time() - t1)

3、共享内存

同一进程下,不同线程共享数据
使用锁来防止内存混乱

import threadingi = 0
lock = threading.Lock()def sum1():global iwith lock:for x in range(1000000):i += xi -= xprint('sum1', i)def sum2():global iwith lock:for x in range(1000000):i += xi -= xprint('sum2', i)if __name__ == '__main__':thr1 = threading.Thread(target=sum1)thr2 = threading.Thread(target=sum2)thr1.start()thr2.start()thr1.join()thr2.join()print('over')

4、定时执行

import threading
import timedef run():print('执行了')if __name__ == '__main__':# 3秒以后干run的活t = threading.Timer(3, run)t.start()

5、线程池

from concurrent.futures import ThreadPoolExecutor, as_completeddef run(i):print('开始执行子线程', i)return iif __name__ == '__main__':pool = ThreadPoolExecutor(3) # 线程并发个数   List = [1, 2, 3, 4, 5]for res in pool.map(run, List):print(res)
'''
开始执行子线程 1
开始执行子线程 2
开始执行子线程 3
1
2
3
开始执行子线程 5
开始执行子线程 4
4
5
'''

http://www.ppmy.cn/news/12081.html

相关文章

华为PIM-SM 动态RP实验配置

目录 建立PIM SM邻居 配置DR 配置动态RP 组成员端DR上配置IGMP 配置PIM安全 配置SPT切换 配置Anycast RP 配置接口的IP地址,并配置路由协议使得全网互通 建立PIM SM邻居 AR5操作 multicast routing-enable 开启组播路由转发功能 int g0/0/0 pim sm …

部分选主元 LU 分解,CGETRF in lapack 选主元时调用 ICAMAX

ICAMAX finds the index of the first element having maximum |Re(.)| |Im(.)| 也就是找出一列 complex 类型的数据中,实部的绝对值 虚部的绝对值 最大的那个元素。这样选出来的主元也还不错。 而不是选择复数模最大的元素; 但是,cublas中…

Acwing——第86场周赛

题目链接 4794. 健身 4795. 安全区域 4796. 删除序列 题目描述 4794. 健身 李华一共要进行 n 组健身训练。 其中,第 i 组训练的时长为 aia_iai​。 李华只做三种运动:胸部(chest)运动、二头肌(biceps)运…

UDS诊断系列介绍10-28服务

本文框架1. 系列介绍1.1 28服务概述2. 28服务请求与应答2.1 28服务请求2.2 28服务正响应2.3 否定应答3. Autosar系列文章快速链接1. 系列介绍 UDS(Unified Diagnostic Services)协议,即统一的诊断服务,是面向整车所有ECU的一种诊…

【Linux】工具使用

文章目录一、Linux 软件包管理器 yum二、 Linux开发工具(1) Linux编辑器-vim使用(2)简单vim配置三、Linux编译器-gcc/g使用四、动态库和静态库五、Linux调试器-gdb使用六、Linux项目自动化构建工具-make/Makefile(1)make/Makefile…

Linux常用命令——vi命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) vi 功能强大的纯文本编辑器 补充说明 vi命令是UNIX操作系统和类UNIX操作系统中最通用的全屏幕纯文本编辑器。Linux中的vi编辑器叫vim,它是vi的增强版(vi Improved)&#xff…

用Python的内置包Tkinter写一个练习系统2.0

登录系统 生日系统 抽奖系统1.0 抽奖系统2.0 抽奖系统3.0 练习系统1.0 练习系统2.0 切换题目 def insert(): with open(d:\\登录系统\\练习一1.1.pickle,rb) as file: lst1pickle.load(file) with open(d:\\登录系统\\练习一1.2.pickle,rb)…

【蓝桥杯】 C++ 【学长带练】刷题统计

文章目录题目描述输入描述输出描述实现代码注意点知识点题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天 做 a 道题目, 周六和周日每天做 b 道题目。请你帮小明计算, 按照计划他将在 第几天实现做题数大于等于 n 题? 输入描述 输入一行包含三个…

按键精灵免字库本地识别OCR

按键精灵免字库识别—基于百度飞桨PaddleOCR的RapidOCR前言为什么为什么有大漠了还要使用其它OCR为什么要使用RapidOCR开发PaddleOCR介绍PaddleOCR使用衍生项目版——小白方案按键精灵post调用图片转base64方法转json方法post调用JVM版改为mavenOcrEngine路径idea Run配置网页版…

蓝队攻击的四个阶段(三)

目录 一, 专业技能储备 1.工具开发技能 2.漏洞挖掘技能 3.代码调试技能 4.侦破拓展技能 二,目标网情搜集 1 何为网情搜集 2. 网情搜集的主要工作 三, 网情搜集的途径 1.专业网站 2.专业开发资源网站 3.目标官网 一, 专…

如何系统地学习 C++ 语言?

C 最大的缺点就是语法复杂,而且难学难精。 学习 C 语言也许一本 K&R 的《C程序设计语言》就够了,但是在 C 世界里,找不到这样一本书。在这个爱速成的年代,大家可能耐不住寂寞花很长时间去学习一门语言,所以可以看…

【蓝桥杯简单篇】Python组刷题日寄Part08

刷题日记?刷题日寄! 萌新备战蓝桥杯python组 🌹 发现有需要纠正的地方,烦请指正! 🚀 欢迎小伙伴们的三连关注! 往期系列: 【蓝桥杯简单篇】Python组刷题日寄Part01 【蓝桥杯简单篇】…

微信小程序页面导航、编程式导航、页面事件、生命周期和WXS脚本

文章目录页面导航1.导航到tarBar页面2.导航到非 tabBar 页面3.后退导航编程式导航1.导航到tabBar页面2.导航到非 tabBar 页面3.后退导航导航传参1. 声明式导航传参2. 编程式导航传参3. 在 onLoad 中接收导航参数页面事件下拉刷新上拉触底数据请求获取中添加loading效果,请求完毕…

会话技术--cookie和session

一、会话跟踪技术的概述 对于会话跟踪这四个词,我们需要拆开来进行解释,首先要理解什么是会话,然后再去理解什么是会 话跟踪: 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接&#…

C语言 atoi 函数解析

文章目录前言atoi函数的介绍atoi函数的使用atoi函数的自我实现写在最后前言 对于atoi函数大家可能会有些陌生&#xff0c;不过当你选择并阅读到这里时&#xff0c;请往下阅读&#xff0c;我相信你能对atoi函数熟悉该函数的头文件为 <stdlib.h> 或 <cstdlib> atoi函…

Python学习笔记-PyQt6工具栏

工具栏工具栏可以有多个&#xff0c;而且可以设置不同的位置参数。4.1工具栏位置参数QtCore.Qt.ToolBarArea.LeftToolBarAreaQtCore.Qt.ToolBarArea.RightToolBarAreaQtCore.Qt.ToolBarArea.TopToolBarAreaQtCore.Qt.ToolBarArea.BottomToolBarAreaQtCore.Qt.ToolBarArea.AllTo…

【学习笔记】【Pytorch】七、卷积层

【学习笔记】【Pytorch】七、卷积层学习地址主要内容一、卷积操作示例二、Tensor&#xff08;张量&#xff09;是什么&#xff1f;三、functional.conv2d函数的使用1.使用说明2.代码实现四、torch.Tensor与torch.tensor区别五、nn.Conv2d类的使用1.使用说明2.代码实现六、池化公…

2022__我的嵌入式入坑之路

目录 一、学习篇 51单片机&#xff1a; python爬虫&#xff1a; stm32单片机&#xff1a; ad&#xff1a; 立创EDA&#xff1a; openmv&#xff1a; ardunio&#xff1a; ESP32&#xff1a; 汇编语言&#xff1a; ROS&#xff1a; FreeRTOS&#xff1a; matlab&a…

自动驾驶中3D目标检测综述

1 背 景 1.1 3D目标检测 3D目标检测是通过输入传感器数据&#xff0c;预测3D目标的属性信息的任务。如何表示3D目标的属性信息是关键&#xff0c;因为后续的预测和规划需要这些信息。在大部分情况下&#xff0c;3D目标被定义为一个立方体&#xff0c;(x,y,z)是立方体的中心坐…

Spark WordCount 案例

文章目录Spark WordCount 案例1、程序连接 Spark2、WordCount 案例示例3、复杂版 WordCount4、Spark 框架WordcountSpark WordCount 案例 1、程序连接 Spark 首先这个Scala spark程序和spark的链接&#xff0c;跟sql编程类似。首先new 一个新的val context SparkContext()对…
最新文章