普通方式开启进程
from multiprocessing import Process
import os
import time
def fun(i):
time.sleep(3)
with open('text','r') as f:
count = int(f.read())
count -= 1
with open('text','w') as f:
f.write(str(count))
print('这是 %s 个子进程,PID为 %s 父进程PID为 %s count:%s'%(i,os.getpid(),os.getppid(),count))
if __name__ == '__main__':
p_s = []
for i in range(5):
p = Process(target=fun,args=(i,))
p_s.append(p)
for p in p_s:
p.start()
继承的方式开启进程
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
def run(self):
print('开启了一个子进程...')
self.fun()
def fun(self):
time.sleep(3)
print('子进程运行了')
if __name__ == '__main__':
p = MyProcess()
p.start()
锁
from multiprocessing import Process,Value,Lock
def get_num(num,lock):
for i in range(10):
lock.acquire()# 获取锁
num.value -= 1
lock.release() # 释放锁
print(num.value)
def put_num(num,lock):
for i in range(10):
lock.acquire() # 获取锁
num.value += 1
lock.release() # 释放锁
print(num.value)
if __name__ == '__main__':
num = Value('i',10) # Value可以在多个进程之间共享数据
lock = Lock() # 实例化一个锁
get_p = Process(target=get_num,args=(num,lock))
get_p.start()
put_p = Process(target=put_num,args=(num,lock))
put_p.start()
get_p.join()
put_p.join()
print(num.value)
信号量
from multiprocessing import Semaphore,Process
import time
def fun(num,lock):
lock.acquire()
print('%s进来了。。。'%num)
time.sleep(1)
lock.release()
print('%s出来了....'%num)
if __name__ == '__main__':
lock = Semaphore(5) # 相当于实例化了一个锁,但是锁有五把钥匙
for i in range(50):
p = Process(target=fun,args=(i,lock))
p.start()
from multiprocessing import Event,Process
import time
def signal_lamp(e):
while True:
if e.is_set(): # 如果当前事件状态为true那么将,状态改为false阻塞进程,模拟实现红灯亮起状态
print('红灯凉了..')
e.clear()# 将event状态改为false
else:# 如果当前事件状态为false那么将,状态改为true允许进程运行,模拟实现绿灯灯亮起状态
print('绿灯凉了....')
e.set()#将event状态改为true
time.sleep(10)
def Car(i,e):
e.wait() # 如果e.is_set()为false则阻塞在这一步,否则运行
print('第%s辆车过去了....'%i)
if __name__ == '__main__':
# Event几种方法:
# event.isSet():返回event的状态值;
# event.wait():
# 如果
# event.isSet() == False将阻塞进程;
# event.isSet() == True 进程正常运行;
# event.set(): 设置event的状态值为True,所有阻塞池的进程激活进入就绪状态, 等待操作系统调度;
# event.clear():恢复event的状态值为False。
e = Event()
sl = Process(target=signal_lamp,args=(e,))
sl.start()
for i in range(10):
p = Process(target=Car,args=(i,e,))
p.start()
生产者消费者模型Queue
from multiprocessing import Queue,Process
def producer(q):
for i in range(20):
q.put('第 %s 个包子' % (i,))
def comsumer(q):
while True:
info = q.get()
if not info:
break
print('消费:%s'%(info,))
if __name__ == '__main__':
q = Queue(20) # 创建一个队列,队列内部实现了锁机制,所以在进程中共享数据是安全的
p_p = Process(target=producer,args=(q,))
p_c = Process(target=comsumer,args=(q,))
p_p.start()
p_c.start()
p_p.join() # 等待生产者完成
q.put(None)# 如果生产者完成了生成,则在队列中存入None如果,消费者读取到None则退出
生产者消费者模型JoinableQueue
from multiprocessing import Process,JoinableQueue
def producer(q):
for i in range(20):
q.put('第 %s 个包子' % (i,))
q.join() # 阻塞,一直阻塞到消费者消费完所有包子(队列中记录了生产的包子个数)
def comsumer(q):
while True:
info = q.get()
print('消费:%s'%(info,))
q.task_done()# 每消费完一个包子,就会发送一个信号到队列。
if __name__ == '__main__':
q = JoinableQueue(20)
p_p = Process(target=producer,args=(q,))
p_c = Process(target=comsumer,args=(q,))
p_p.start()
p_c.daemon = True # 将消费者进程设置为守护进程,那么当主进程的代码全部执行完毕,则会退出消费者进程
p_c.start()
p_p.join() # 主进程等待生产者进程完成
'''
这段代码的中心思想:
首先:生产者进程q.join()会等待消费者吃完所有包子之后才会结束
然后:主进程 p_p.join() 会等待生产者进程结束
最后:p_c.daemon = True 会等待主进程结束,然后结束
导致的结果:消费者吃完所有包子 -> 生产者进程结束 -> 主进程代码执行完毕 -> 消费者进程(守护进程)结束
'''
管道
from multiprocessing import Process,Pipe
def producer(con):
con1,con2 = con
con2.close()
for i in range(20):
con1.send('第 %s 个包子' % (i,))
def comsumer(con):
con1, con2 = con
con1.close()
while True:
try:
info = con2.recv()
except EOFError:
con2.close()
break
print('消费:%s'%(info,))
if __name__ == '__main__':
# 管道内部没有实现锁机制,需要自己实现。所以管道在多进程中共享数据是不安全的
con1,con2 = Pipe() # 管道的核心,如果是con1发送,那么只能用con2接收
p_p = Process(target=producer,args=((con1,con2),))
p_c = Process(target=comsumer,args=((con1,con2),))
p_p.start()
p_c.start()
p_p.join()
con1.close()
进程池
from multiprocessing import Pool
import os
import time
def fun(num):
return num + 1
def call_back(num):
with open('a.txt','a') as f:
f.write(str(num))
if __name__ == '__main__':
pool = Pool(os.cpu_count()+1) # os.cpu_count() 可以计算出当前计算机的核数
# # map方法 用时:0.2000112533569336
# start = time.time()
# res = pool.map(fun,range(100)) # pool.map(函数,可迭代对象) 将可迭代对象中的每一个元素传入函数计算,并且将计算结果返回 res得到一个列表
# pool.close() # 想要主进程等待进程池中的任务全部完成。首先得关闭进程池,使新任务无法在放入进程池。之后在使用pool.join()来使主进程阻塞等待
# pool.join()
# print(res)
# print(time.time()-start)
# #apply(同步)方法,跟没开多进程一样,一个一个执行 用时 0.15600895881652832
# start = time.time()
# for i in range(100):
# res = pool.apply(func=fun,args=(i,)) # pool.apply(func=函数,args=(参数,)) 可以得到函数的返回值
# print(res)
# print(time.time()-start)
# apply(异步)方法 用时 0.08100461959838867
# pool.apply(func=函数,args=(参数,),callback=回调函数)
# 使用 res.get()可以得到函数的返回值。
# 回调函数接收一个参数,参数就是func的返回值,自动传参。(回调函数由主进程调用)
# #回调函数的练习
# start = time.time()
# res_l = []
# for i in range(100):
# res = pool.apply_async(func=fun,args=(i,),callback=call_back)
# res_l.append(res)
# pool.close()
# pool.join()
# print(time.time()-start)