多任务
多任务:简单地说,就是操作系统可以同时运行多个任务。
1、一个cpu同一个时刻只能执行一个任务,因为切换速度非常快,感觉是多任务
2、操作系统已经设置好cpu的使用权如何分配,自己写的代码无权干涉
3、任务调度有很多算法,如:1)优先级调度 2)时间轮转 等…
程序和进程
- 编写完毕的代码,在没有运行的时候,称之为程序。
- 正在运行着的代码,就成为进程。
进程,除了包含代码以外,还有需要运行的环境等,所以和程序是有区别的。
fork()函数
当程序执行到os.fork()时,操作系统会创建一个新的进程(子进程),然后复制父进程的所有信息到子进程中。
fork函数,只在Unix/Linux/Mac上运行,windows不可以
父进程和子进程都会从fork()函数中得到一个返回值,在子进程中这个值一定是0,而父进程中是子进程的 id号。
子进程永远返回0,而父进程返回子进程的ID。
- getpid():获得该进程的ID
- getppid():获得父进程的ID
多进程中,每个进程中所有数据(包括全局变量)都各有拥有一份,互不影响。
父进程、子进程执行顺序没有规律,完全取决于操作系统的调度算法。
multiprocessing
由于Windows没有fork调用,而Python是跨平台的,自然也应该提供一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块。
multiprocessing模块提供了一个Process类来代表一个进程对象。
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
print('子进程运行中,name= %s ,pid=%d...' % (name, os.getpid()))
if __name__ == '__main__':
print('父进程 %d.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('子进程将要执行')
p.start()
p.join()
print('子进程已结束')
代码运行结果:
创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,这样创建进程比fork()还要简单。
join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。
Process语法结构如下:
Process([group [, target [, name [, args [, kwargs]]]]])
target:表示这个进程实例所调用对象
args:表示调用对象的位置参数元组
kwargs:表示调用对象的关键字参数字典
name:为当前进程实例的别名
group:大多数情况下用不到
Process类常用方法:
is_alive():判断进程实例是否还在执行
join([timeout]):是否等待进程实例执行结束,或等待多少秒
start():启动进程实例(创建子进程)
run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法
terminate():不管任务是否完成,立即终止
Process类常用属性:
name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数
pid:当前进程实例的PID值
1、p = Process(target=run_proc, args=(‘test’,))初始化状态
2、p.start() 就绪状态,一旦获取使用cpu使用权运行,运行状态
3、运行过程中,cpu可能切换走,变成阻塞状态,阻塞状态结束后变成就绪状态,等待获取cpu使用权
4、直到进程的功能函数运行完毕,进程死亡
如果进程中有sleep、input、join也是阻塞状态
创建新的进程还能够使用类的方式,可以自定义一个类,继承Process类,每次实例化这个类的时候,就等同于实例化一个进程对象。
from multiprocessing import Process
from time import sleep
import random
import os
class Sing(Process):
def run(self):
for i in range(3):
print("Sing...%d...%d" % (i, os.getpid()))
sleep(random.random())
class Dance(Process):
def run(self):
for i in range(3):
print("Dance...%d...%d" % (i, os.getpid()))
sleep(random.random())
sing = Sing()
sing.start()
dance = Dance()
dance.start()
sleep(random.random())
print("game over...")
代码运行结果:
两种方式的对比
1、方法
2、继承类
继承类是以面向对象考虑这个事的,所以业务逻辑复杂,建议使用继承类,更好理解