多任务编程
进程
什么是进程
1.程序就是没有执行的二进制代码
2.进程就是运行的程序
进程调度
时间片轮转:
cpu不会闲置,会将要运行的程序轮换执行(例如要运行qq和微信,可能会将qq先运行0.1秒,然后再将微信执行0.2秒,运行多少时间是随机的)
并发:交替运行
并行:同一时间点一起运行
fork创建进程
import os
#返回进程的pid
pid = os.fork()
if pid == 0:
print("我是子进程")
else:
print("我是主进程")
实例
import os
import time
def sing():
for i in range(5):
print("唱歌")
def dance():
for i in range(5):
print("跳舞")
#开始时间
start = time.time()
#创建多进程
pid = os.fork()
if pid == 0:
sing()
else:
dance()
print(time.time() - start)
1.父程序和子程序运行顺序是随机的
2.fork得到的结果是0,那么这个程序就是子程序。如果不是0,那么这个进程就是父进程,并且这个结果就是其子进程的pid
3.os.getpid() 得到当前进程的id
4.os.getppid() 得到当前进程父进程的id
修改全局变量
import os
num = 0
#创建进程
pid = os.fork()
if pid == 0:
num += 1
print(num)
else:
num += 1
print(num)
总结:子进程在创建的时候会复制父进程的内存到自己的内存中
多次fork
import os
#创建进程
pid = os.fork()
if pid == 0:
#子进程打印1
print(1)
else:
#父进程打印2
print(2)
#两个进程再生成进程
pid = os.fork()
#父进程新生成的子进程和子进程生成的进程打印3
if pid == 0:
print(3)
#父进程打印4, 子进程打印4
else:
print(4)
总共会打印6次
注意:fork实现的多进程只能运用在linux系统
Process实现多进程
#导包
import os
import time
from multiprocessing import Process
#定义两个方法
def sing():
print("sing里面的:{}".format(os.getpid()))
for i in range(5):
print("唱歌")
time.sleep(1)
def dance():
print("dance里面的:{}".format(os.getpid()))
for i in range(5):
print("跳舞")
time.sleep(1)
#定义多进程方法
def process():
#创建进程
ps = Process(target=sing)
#启动进程
ps.start()
#创建进程,执行某个方法
pd = Process(target=dance)
pd.start()
print("process里面的:{}".format(os.getpid()))
#Windows下,多进程必须放在这个方法下才能运行
if __name__ == "__main__":
process()
进程对象.join()方法 等待当前进程执行完毕再往下执行
#Process参数
#windows 实现多进程
import os
import time
from multiprocessing import Process
def sing(x):
for i in range(x):
print("唱歌")
time.sleep(1)
def dance(x, name):
for i in range(x):
print(f"{name}跳舞")
time.sleep(1)
def process():
start = time.time()
ps = Process(target=sing, args=(5,))
ps.start()
pd = Process(target=dance, args=(10,), kwargs={"name": "ddd"})
pd.start()
#等待子进程执行完毕,再执行
ps.join()
pd.join()
print(time.time() - start)
if __name__ == "__main__":
process()
Process类继承
代码
#导入进程类
from multiprocessing import Process
#继承类
class ProcessClass(Process):
#初始化
def __init__(self, name):
super(ProcessClass, self).__init__()
self.name = name
#run 方法必须写,调用start就是调用这个方法
def run(self):
print(self.name + "ok")
if __name__ == '__main__':
p = ProcessClass("python")
p.start()
进程池
解决每一个任务创建一个进程占用内存空间大的问题
import os
import time
from multiprocessing import Pool
# 打印方法
def work(msg):
print(f"{os.getpid()},{msg}")
time.sleep(1)
# 创建3个进程池
pool = Pool(3)
for i in range(8):
# 多进程异步调用打印方法
pool.apply_async(work, (i,))
# 关闭进程池
pool.close()
# 等待进程执行完毕
pool.join()
进程间的通信
队列
import os
import time
from multiprocessing import Queue, Process
# 定义一个写函数,往队列里写
def write(q):
for i in ["吕布", "貂蝉", "小乔", "周瑜"]:
q.put(i)
print(f"{os.getpid()}在写{i}")
time.sleep(1)
# 定义一个读方法,从队列里读取
def read(q):
while True:
if not q.empty():
print(f"{os.getpid()}在读{q.get()}")
time.sleep(1)
else:
break
if __name__ == '__main__':
# 定义一个队列,不传参数,有多少塞多少
q = Queue()
# 创建子进程,把队列作为参数传入目标函数中
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动进程
pw.start()
# pw写入完毕再执行读
pw.join()
pr.start()
pr.join()
其他
孤儿进程:父进程先于子进程执行完毕
僵尸进程:子进程执行完后,父进程还在沉睡,没有去回收子进程的内存空间
执行top可以查看进程 zombie代表僵尸进程的数量
找出僵尸进程 后面带<defunct>的就是僵尸 ps -ef | grep "def"
如何结束僵尸进程:结束其父进程 kill -9 僵尸进程的ppid
守护进程:父进程先于子进程执行完毕,子进程会被1号进程接管,就会变成守护进程
网友评论