Python学习第49天(多进程调用)
昨天的生产者消费者模型其实自己没有怎么认真听,因为前几天上班太忙消耗太大,导致昨晚太困,多次电脑砸脸,所以今天再详细说一下生产者消费者模型。
主要是利用queue来实现一个生产者和消费者之前的联通,其实在之前曾经利用过列表来实现,但是明显那种方式非常的不合适,生产者和消费者之间的联系太强了,基本都是生产完开始吃,亦或者边生产边吃,没有体现出生产者和消费者之间的随机联系。
下面这版本应该是最初的,通过判断队列q是否为空来时消费者和生产者之间取得联系:
import random,queue,time import threading q = queue.Queue() def product(name): count = 0 while count < 10 : print('%s is making.'%name) time.sleep(random.randrange(3)) q.put(str(count) + 'baozi') print('%s had made No.%s baozi'%(name,count)) count += 1 def consumer(name): count = 0 # print(q.empty()) while count < 10 : if q.empty(): data = q.get() print('\033[32; %s is eating %s \033[0m'%(name,data)) time.sleep(random.randrange(4)) else: print('no baozi anymore') print('waiting') count += 1 if __name__ == '__main__': t1 = threading.Thread(target = product ,args = ('zhaolei',)) t2 = threading.Thread(target = consumer , args = ('zjl',)) t3 = threading.Thread(target = consumer , args = ('mayday',)) t4 = threading.Thread(target = consumer , args = ('golo',)) t1.start() t2.start() t3.start() t4.start()
上面这个是具有了一定的结耦,但是还不是很明显,我们昨天说过q.join()和 q.task_done()
当完成一个队列加入的时候 q.task_done()就会释放信号,被q.join()接收到,如果没有接收到信息,该线程会在q.join()这里进行等待,知道收到为止,上面我们是通过q.empty()实现的,下面解锁一下新的情况吧
import random,queue,time import threading q = queue.Queue() def product(name): count = 0 while count < 10 : print('%s is making.'%name) time.sleep(random.randrange(3)) q.put(str(count) + 'baozi') print('%s had made No.%s baozi'%(name,count)) q.task_done() count += 1 def consumer(name): count = 0 while count < 10: print('%s is waiting'%name) q.join() data = q.get() print('\033[32; %s is eating %s \033[0m'%(name,data)) time.sleep(random.randrange(2)) # print(q.empty()) if __name__ == '__main__': t1 = threading.Thread(target = product ,args = ('zhaolei',)) t2 = threading.Thread(target = consumer , args = ('zjl',)) t3 = threading.Thread(target = consumer , args = ('mayday',)) t4 = threading.Thread(target = consumer , args = ('golo',)) t1.start() t2.start() t3.start() t4.start()
同时这样的q.join()和 q.task_done()之间的信息交互,我们也可以反过来用,正好就是顾客吃完一个,老板才会开始继续做
以上就是多线程的部分了,下面进入多线程部分
Python为了弥补不能使用多核电脑福利的遗憾,引入了设置进程的概念,这样就是多个GIL,实现了的资源利用的最大化
专业的说法:由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。
multiprocessing包是Python中的多进程管理包。与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。
先看一下多进程的调用方式:
from multiprocessing import Process import time def f(name): time.sleep(1) print('hello', name,time.ctime()) if __name__ == '__main__': p_list=[] for i in range(3): p = Process(target=f, args=('alvin',)) p_list.append(p) p.start() for i in p_list: p.join() print('end')
方式2:
from multiprocessing import Process import time class MyProcess(Process): def __init__(self): super(MyProcess, self).__init__() #self.name = name def run(self): time.sleep(1) print ('hello', self.name,time.ctime()) if __name__ == '__main__': p_list=[] for i in range(3): p = MyProcess() p.start() p_list.append(p) for p in p_list: p.join() print('end')
调用的方式来看,基本是和多线程很像
然后是这个类的一些实际属性吧:
构造方法:
Process([group [, target [, name [, args [, kwargs]]]]])
group: 线程组,目前还没有实现,库引用中提示必须是None;
target: 要执行的方法;
name: 进程名;
args/kwargs: 要传入方法的参数。
实例方法:
is_alive():返回进程是否在运行。
join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。
start():进程准备就绪,等待CPU调度
run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。
terminate():不管任务是否完成,立即停止工作进程
属性:
daemon:和线程的setDeamon功能一样
name:进程名字。
pid:进程号。
getpid:获得进程号。
getppid:获得父类进程的进程号。
今天的内容就是这些,我有点想不起来socket部分的知识了,所以明天更新了多进程周后,我打算开始转回去进行知识的复习,正好下周要去查办一个非常重要的人。
今晚要睡得正常,明天去理个发。