@TOC
前言
本文主要介绍python单进程多进程。Python
要进行多进程操作,需要用到muiltprocessing
库,其中的Process
类跟threading
模块的Thread
类很相似。进程
是指一个程序在给定数据集合上的一次执行过程,是系统进行资源分配和运行调用的独立单位。可以简单地理解为操作系统中正在执行的程序。也就说,每个应用程序都有一个自己的进程。
每一个进程启动时都会最先产生一个线程,即主线程。然后主线程会再创建其他的子线程。python
的多进程性能要明显优于多线程,因为cpython
的GIL
对性能做了约束。
一、 单进程
以吃饭睡觉打豆豆为例。单进程需要先吃饭,在睡觉,最后打豆豆,次序不可打乱。
# 单进程
import time
def eat():
for i in range(3):
print("吃饭……")
time.sleep(1)
def sleep():
for i in range(3):
print("睡觉……")
time.sleep(1)
def play():
for i in range(3):
print("打豆豆……")
time.sleep(1)
if __name__ == '__main__':
eat()
sleep()
play()
二、 多进程
以吃饭睡觉打豆豆为例。多进程对吃饭,睡觉,打豆豆,可以交叉进行,无需按序执行。
# 多进程
import multiprocessing # 导入进程包
import time
def eat():
for i in range(3):
print("吃饭……")
time.sleep(1)
def sleep():
for i in range(3):
print("睡觉……")
time.sleep(1)
def play():
for i in range(3):
print("打豆豆……")
time.sleep(1)
if __name__ == '__main__':
#target:指定函数名
eat_process = multiprocessing.Process(target=eat) # 通过进程类创建进程对象
sleep_process = multiprocessing.Process(target=sleep)
play_process = multiprocessing.Process(target=play)
eat_process.start()
sleep_process.start()
play_process.start()
三、 带参多进程
target
:指定执行的函数名。此处注意,若只有一个元素,那个逗号也是不可以省略的。args
:使用元组方式给指定任务传参kwargs
:使用字典方式给指定任务传参
```java带参多进程
import time
import multiprocessing
def eat(num,name):
for i in range(num):
print(name+"吃饭……")
time.sleep(1)
def sleep(num,name):
for i in range(num):
print(name+"睡觉……")
time.sleep(1)
def play(num,name):
for i in range(num):
print(name+"打豆豆……")
time.sleep(1)
if name == 'main':
# target:指定执行的函数名。此处注意,若只有一个元素,那个逗号也是不可以省略的。
# args:使用元组方式给指定任务传参
# kwargs:使用字典方式给指定任务传参
eat_process = multiprocessing.Process(target=eat,args=(3,'vitian')) # 通过进程类创建进程对象
sleep_process = multiprocessing.Process(target=sleep,args=(3,'anna'))
play_process = multiprocessing.Process(target=play,args=(3,'prince'))
eat_process.start()
sleep_process.start()
play_process.start()
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/fedd765f33e344c69cfa7f310a3ed8b0.png)
# 四、 获取进程的编号
以吃饭睡觉打豆豆为例。主进程相同,子进程各不同。
```java
# 获取进程的编号
import time
import multiprocessing
import os
def eat(num,name):
print("吃饭的进程ID:", os.getpid())
print("吃饭的主进程ID:", os.getppid())
for i in range(num):
print(name+"吃饭……")
time.sleep(1)
def sleep(num,name):
print("睡觉的进程ID:", os.getpid())
print("睡觉的主进程ID:", os.getppid())
for i in range(num):
print(name+"睡觉……")
time.sleep(1)
def play(num,name):
print("打豆豆的进程ID:", os.getpid())
print("打豆豆的主进程ID:", os.getppid())
for i in range(num):
print(name+"打豆豆……")
time.sleep(1)
if __name__ == '__main__':
# target:指定执行的函数名
# args:使用元组方式给指定任务传参
# kwargs:使用字典方式给指定任务传参
eat_process = multiprocessing.Process(target=eat,args=(3,'vitian')) # 通过进程类创建进程对象
sleep_process = multiprocessing.Process(target=sleep,kwargs={"num": 2, "name":"anna"})
play_process = multiprocessing.Process(target=play,args=(1,'prince'))
print("主进程ID:", os.getpid())
eat_process.start()
sleep_process.start()
play_process.start()
五、 主进程会等待所有的子进程执行结束再结束
# 主进程会等待所有的子进程执行结束再结束
import multiprocessing
import time
def eat():
for i in range(10):
print("吃饭睡觉打豆豆……")
time.sleep(0.5)
if __name__ == '__main__':
eat_process = multiprocessing.Process(target=eat)
eat_process.start()
time.sleep(1)
print("主进程结束了……")
六、 子进程守护
设置子进程守护,当主进程结束时,子进程也不再继续执行,直接结束。
七、 多线程与单线程的取舍
多线程在IO密集型的操作下似乎也没有很大的优势(IO操作的任务再繁重一些就能体现出优势),在CPU密集型的操作下明显地比单线程线性执行性能更差,但是对于网络请求这种忙等阻塞线程的操作,多线程的优势便非常显著了。
多进程无论是在CPU密集型还是IO密集型以及网络请求密集型(经常发生线程阻塞的操作)中,都能体现出性能的优势。不过在类似网络请求密集型的操作上,与多线程相差无几,但却更占用CPU等资源,所以对于这种情况下,我们可以选择多线程来执行。