第34篇 通过类的方法开启子进程,以及传参,join阻塞,daemon守护进程,同步Lock,Samphore信号量,event事件
Posted cavalier-chen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第34篇 通过类的方法开启子进程,以及传参,join阻塞,daemon守护进程,同步Lock,Samphore信号量,event事件相关的知识,希望对你有一定的参考价值。
内容大纲:
Process开启子进程
#另外一种开启子进程的方式
#join控制子进程
#守护进程
同步控制
#锁 Lock
#信号量 Samphore
#事件 Event
#join控制子进程
#p.join() 阻塞p进程,p进程执行结束,才结束阻塞。
import time
import random
from multiprocessing import Process
def func(index):
time.sleep(random.random())
print(‘第%s个邮件已经发送完毕‘%index)
if __name__ == ‘__main__‘:
for i in range(10):
Process(target=func,args=(i,)).start()
print(‘10个邮件已经发送完毕‘)
10个邮件已经发送完毕
第2个邮件已经发送完毕
第5个邮件已经发送完毕
第8个邮件已经发送完毕
第6个邮件已经发送完毕
第1个邮件已经发送完毕
第7个邮件已经发送完毕
第0个邮件已经发送完毕
第9个邮件已经发送完毕
第3个邮件已经发送完毕
第4个邮件已经发送完毕
#发送10 个邮件编程了同步事件 就是一个执行了在执行另一个
import time
import random
from multiprocessing import Process
def func(index):
time.sleep(random.random())
print(‘第%s个邮件已经发送完毕‘%index)
if __name__ == ‘__main__‘:
p_list = []
for i in range(10):
p = Process(target=func,args=(i,))
p_list.append(p)
for p in p_list:
p.start()
p.join()
#开启一个进程,进程结束之后再开启下一个进程,
print(‘10个邮件已经发送完毕‘)
第0个邮件已经发送完毕
第1个邮件已经发送完毕
第2个邮件已经发送完毕
第3个邮件已经发送完毕
第4个邮件已经发送完毕
第5个邮件已经发送完毕
第6个邮件已经发送完毕
第7个邮件已经发送完毕
第8个邮件已经发送完毕
第9个邮件已经发送完毕
10个邮件已经发送完毕
#怎样才能够实现,10个邮件并发进行,等到是个邮件都完成发送,再汇报10个有家你已经发送完毕???
import time
import random
from multiprocessing import Process
def func(index):
time.sleep(random.random())
print(‘第%s个邮件已经发送完毕‘%index)
if __name__ == ‘__main__‘:
p_list = []
for i in range(10):
p = Process(target=func,args=(i,))
p.start()
p_list.append(p)
#告诉操作系统开启10 个进程
#把10个进程放进一个列表
for p in p_list:
p.join()
#p_list里面的进程当做一个整体,这个证题里面的都执行完了,再进行主进程
#但是p_list中的是个进程是并发的
print(‘10个邮件已经发送完毕‘)
第2个邮件已经发送完毕
第4个邮件已经发送完毕
第3个邮件已经发送完毕
第1个邮件已经发送完毕
第9个邮件已经发送完毕
第0个邮件已经发送完毕
第6个邮件已经发送完毕
第5个邮件已经发送完毕
第7个邮件已经发送完毕
第8个邮件已经发送完毕
10个邮件已经发送完毕
#调用类方法,开启进程
from multiprocessing import Process
import os
class MyProcess(Process):#继承Process类
def run(self):
print(‘子进程:‘,os.getpid(),os.getppid())
if __name__ == ‘__main__‘:
p = MyProcess()#实例化对象
p.start()#启动进程
子进程: 10208 8564
#调用类方法,开启进程的方法,怎么给进程传递参数???
from multiprocessing import Process
import os
class MyProcess(Process):
def __init__(self,args):
super().__init__()#调用父类的初始化方法
self.args = args#传入参数
def run(self):
print(‘子进程:‘,os.getpid(),os.getppid(),self.args)
if __name__ == ‘__main__‘:
p = MyProcess(‘参数‘)
p.start() #开启一个进程的时候调用的是这个类的run方法
print(‘主进程:‘,os.getpid(),os.getppid())
主进程: 6804 7136
子进程: 9668 6804 参数
#守护进程deamon
#某个进程设置成守护进程 已经要在他开始之前
import os,time
from multiprocessing import Process
def func():
print(‘子进程start‘)
time.sleep(3)
print(‘子进程 end‘)
if __name__ == ‘__main__‘:
p = Process(target=func)
p.daemon = True#主进程结束不会等待子进程,
p.start()
time.sleep(2)
print(‘主进程‘)
子进程start
主进程
#为什么会出现子进程没有执行结束,主进程就结束完毕
#正常情况下,主进程会等待子进程的结束,才会结束,最后给子进程回收资源
#守护进程会随着主进程的结束 而提前结束
#守护进程的举例
#如果主程序的代码已经执行完毕,但是子进程代码还没有执行完,守护进程都不会继续执行
import time,os,random
from multiprocessing import Process
def func1():
count = 1
while True:
time.sleep(0.5)
print(count*‘*‘)
count += 1
def func2():
print(‘func2 start‘)
time.sleep(5)
print(‘func2 end‘)
if __name__ == ‘__main__‘:
p1 = Process(target=func1)
p1.daemon = True
p1.start()
p2 = Process(target=func2)
p2.start()
time.sleep(3)
print(‘主进程‘)
func2 start
*
**
主进程
func2 end
#守护进程的应用:程序的报活
每隔5分钟向主机汇报自己的运行状况
#锁的应用
#买车票
import json,time
from multiprocessing import Process
def search(person):
with open(‘ticket.txt‘) as f :
dic = json.load(f)
time.sleep(0.2)
print(‘%s查询余票:%s‘%(person,dic[‘count‘]))
def get_ticket(person):
with open(‘ticket.txt‘) as f :
dic =json.load(f)
time.sleep(0.2)
if dic[‘count‘] >0 :
print(‘%s 买到票了‘%person)
dic[‘count‘] -= 1
time.sleep(0.2)
with open(‘ticket.txt‘,‘w‘) as f :
json.dump(dic,f)
else:
print(‘%s没有买到票‘%person)
if __name__ == ‘__main__‘:
for i in range(10):
p = Process(target=get_ticket,args=(‘person :%s‘%i,))
p.start()
ticket.txt文本里面的内容:{"count": 3}
person :9 买到票了
person :2 买到票了
person :5 买到票了
person :7 买到票了
person :4 买到票了
person :6 买到票了
person :1 买到票了
person :8 买到票了
person :0 买到票了
person :3 买到票了
ticket.txt文本里面的内容最后修改为:
{"count": 1}
#为什么明明只有3张票 结果却显示都买到票了???
#异步的情况下,多个进程可能同时修改同一份资源
#为了保证数据的安全,需要引入锁的概念
#给这个修改的过程加锁
#加锁的效果
降低了程序的执行效率 让原来是同时执行的代码变成了顺序执行,异步变成同步
但是保证了数据的安全
#买票的例子
#文件信息:
ticket.txt:{"count": 3}
import json,time
from multiprocessing import Process,Lock
def search(person):
with open(‘ticket.txt‘) as f :
dic = json.load(f)
time.sleep(0.2)
print(‘%s查询余票:%s‘%(person,dic[‘count‘]))
def get_ticket(person):
with open(‘ticket.txt‘) as f :
dic =json.load(f)
time.sleep(0.2)
if dic[‘count‘] >0 :
print(‘%s买到票了‘%person)
dic[‘count‘] -= 1
time.sleep(0.2)
with open(‘ticket.txt‘,‘w‘) as f :
json.dump(dic,f)
else:
print(‘%s没有买到票‘%person)
def ticket(person,lock):
search(person)
lock.acquire()
get_ticket(person)#给买票的过程上锁
lock.release()
if __name__ == ‘__main__‘:
lock = Lock()
for i in range(10):
p = Process(target=ticket,args=(‘person :%s‘%i,lock))#这里有个坑逗号不能少
p.start()
#文件修改为:
ticket.txt:{"count": 0}
person :9查询余票:3
person :4查询余票:3
person :9买到票了
person :7查询余票:3
person :0查询余票:3
person :2查询余票:3
person :4买到票了
person :6查询余票:2
person :3查询余票:2
person :5查询余票:2
person :1查询余票:2
person :8查询余票:2
person :7买到票了
person :0没有买到票
person :2没有买到票
person :6没有买到票
person :3没有买到票
person :5没有买到票
person :1没有买到票
person :8没有买到票
#并发执行的例子
import time
from multiprocessing import Process
def func(num):
time.sleep(1)
print(‘并发执行‘,num)
if __name__ == ‘__main__‘:
for i in range(10):
p = Process(target= func,args=(i,))
p.start()
并发执行 4
并发执行 0
并发执行 5
并发执行 1
并发执行 2
并发执行 3
并发执行 7
并发执行 6
并发执行 9
并发执行 8
#锁的例子
#谁先拿到锁 谁就先进入 同步的程序
import time
from multiprocessing import Process,Lock
def func(num,lock):
time.sleep(1)
print(‘异步执行‘,num)
lock.acquire()
time.sleep(0.5)
print(‘ 同步执行‘,num)
lock.release()
if __name__ == ‘__main__‘:
lock = Lock()
for i in range(10):
p = Process(target= func,args=(i,lock))
p.start()
异步执行 0
异步执行 5
异步执行 7
异步执行 3
同步执行 0
异步执行 8
异步执行 4
异步执行 1
异步执行 6
异步执行 2
异步执行 9
同步执行 5
同步执行 7
同步执行 3
同步执行 8
同步执行 4
同步执行 1
同步执行 6
同步执行 2
同步执行 9
#插入图片#############
#以上的的锁的概念 都是互斥锁的概念
from multiprocessing import Process,Lock
lock = Lock()
lock.acquire()
print(‘456‘)#lock没有归还程序阻塞
lock.acquire()
print(‘123‘)
lock.release()
--->456
#信号量
能够同时提供服务的最大数量
#插入图片#######################
#没有归还钥匙的情况
import time,random
from multiprocessing import Process,Semaphore
def ktv(person,sem):
sem.acquire()
print(‘%s走进ktv‘%person)
time.sleep(random.randint(1,3))
print(‘ %s走出ktv‘%person)
#没有归还钥匙,四个钥匙被取走之后,程序被阻塞
if __name__ == ‘__main__‘:
sem = Semaphore(4)#信号量设置成4
for i in range(10):
p = Process(target=ktv,args=(‘person:%s‘%i,sem))
p.start()
person:0走进ktv
person:3走进ktv
person:9走进ktv
person:2走进ktv
person:9走出ktv
person:0走出ktv
person:2走出ktv
person:3走出ktv
#归还钥匙
import time,random
from multiprocessing import Process,Semaphore
def ktv(person,sem):
sem.acquire()
print(‘%s走进ktv‘%person)
time.sleep(random.randint(1,3))
print(‘ %s走出ktv‘%person)
sem.release()
if __name__ == ‘__main__‘:
sem = Semaphore(4)#信号量设置成4
for i in range(10):
p = Process(target=ktv,args=(‘person:%s‘%i,sem))
p.start()
person:1走进ktv
person:5走进ktv
person:3走进ktv
person:8走进ktv
person:1走出ktv
person:0走进ktv
person:3走出ktv
person:6走进ktv
person:8走出ktv
person:4走进ktv
person:5走出ktv
person:7走进ktv
person:6走出ktv
person:2走进ktv
person:0走出ktv
person:9走进ktv
person:7走出ktv
person:2走出ktv
person:4走出ktv
person:9走出ktv
控制信号量的机制:
计数器+锁
#什么是事件??
让事件暂停,叫做阻塞事件:
调用wait()方法
wait()是否能够阻塞,需要进一步看事件event内部的属性
控制event的属性:
set()将属性的值改成True
clear()将属性的值改成False
is_set() 判断当前的属性是否是True
#交通信号灯
import time,random
from multiprocessing import Process,Event
def traffic_light(e):
while True:
if e.is_set():
time.sleep(2)
print(‘ 33[31m红灯亮了 33[0m‘)
e.clear()
else:
time.sleep(2)
print(‘ 33[32m绿灯亮了 33[0m‘)
e.set()
def car(e,i):
if not e.is_set():
print(‘car:%s在等待‘%i)
e.wait()
print(‘car:%s通过了‘%i)
if __name__ == ‘__main__‘:
e = Event()
p = Process(target=traffic_light,args=(e,))
p.daemon = True #设置成守护进程
p.start()
p_list = []
for i in range(20):
time.sleep((random.randrange(0,3,2)))
p = Process(target=car,args=(e,i))
p.start()
p_list.append(p)
for i in p_list:i.join()
car:0在等待
car:1在等待
car:2在等待
绿灯亮了
car:0通过了
car:1通过了
car:2通过了
car:3通过了
红灯亮了
car:4在等待
绿灯亮了
car:4通过了
car:5通过了
红灯亮了
car:6在等待
绿灯亮了
car:6通过了
car:7通过了
红灯亮了
car:8在等待
绿灯亮了
car:8通过了
car:9通过了
红灯亮了
绿灯亮了
car:10通过了
car:11通过了
car:12通过了
car:14通过了
car:13通过了
红灯亮了
car:16在等待
car:15在等待
绿灯亮了
car:15通过了
car:16通过了
car:18通过了
car:17通过了
红灯亮了
car:19在等待
绿灯亮了
car:19通过了
以上是关于第34篇 通过类的方法开启子进程,以及传参,join阻塞,daemon守护进程,同步Lock,Samphore信号量,event事件的主要内容,如果未能解决你的问题,请参考以下文章