一、多进程
开启子进程的两种方式
方式一:
from multiprocessing import Process import time def func(name): print('%s is going' % name) time.sleep(3) print('%s is done' % name) if __name__ == '__main__': a = Process(target=func, args=('jack',)) # 必须加逗号 a.start() print('asdwad')
方式二:
from multiprocessing import Process import time class MYfunc(Process): def __init__(self, name): super().__init__() # 继承Process的方法 self.name = name def run(self): # 默认的函数名为run,不能去修改 print('%s is going' % self.name) time.sleep(3) print('%s is done' % self.name) if __name__ == '__main__': a = MYfunc('jack') a.start() print('asdwad')
查看进程的pid------------------os.getpid() 方法/ os.getppid
僵尸进程:一个进程出发子进程后,子进程执行结束后,没有回收的,任然保存在进程中的,这种称谓僵尸进程。
孤儿进程:一个父进程退出了,而他的子进程还在运行,那么这些子进程就是孤儿进程,会被init进程回收。
Process对象的其他方法和属性
jion()方法(回收僵尸进程,等子进程结束了,回收子进程,在去做接下来的工作)
is_alive() 判断进程是活的还是死的,返回TRUE/FALSE
p.start():启动进程,并调用该子进程中的p.run()
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True
p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间。
守护进程
1.守护进程会在主进程代码结束后就终止
2.守护进程内无法在开启子进程,否则抛出异常
from multiprocessing import Process import time def func(name): print('%s is going' % name) time.sleep(3) print('%s is done' % name) if __name__ == '__main__': a = Process(target=func, args=('jack',)) # 必须加逗号 a.daemon = True # 必须在主进程结束前开启 a.start() print('主进程')
互斥锁(保证共享数据的安全)
(特点:由并发变成了串行,降低了效率,避免了竞争)
import os import time from multiprocessing import Process, Lock def work(lock): lock.acquire() # 上锁 print('%s is running' % os.getpid()) time.sleep(2) print('%s is done' % os.getpid()) lock.release() # 解锁 if __name__ == '__main__': lock = Lock() for i in range(3): p = Process(target=work, args=(lock,)) # 需要把所传给子进程;为了保证使用的是同一把锁 p.start()
队列(推荐使用)
创建队列的类(底层就是以管道和锁的方式实现)
from multiprocessing import Queue q = Queue(3) # 指定允许的最大的项数 # 1 q.put方法用以插入数据到队列中, # put方法还有两个可选参数:blocked和timeout。
如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。 # 2 q.get方法可以从队列读取并且删除一个元素。 # 同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常. # 3 q.get_nowait():同q.get(False) # 4 q.put_nowait():同q.put(False) # 5 q.empty():调用此方法时q为空则返回True,该结果不可靠,比如在返回True的过程中,如果队列中又加入了项目。 # 6 q.full():调用此方法时q已满则返回True,该结果不可靠,比如在返回True的过程中,如果队列中的项目被取走。 # 7 q.qsize():返回队列中目前项目的正确数量,结果也不可靠,理由同q.empty()和q.full()一样
生产者消费者模型
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
import random import time from multiprocessing import Process, JoinableQueue def consumer(q, name): while True: res = q.get() time.sleep(random.randint(1, 3)) print('