众所周知,python的多线程提供的只是并发性,不会实际加快运行效率。而多进程则是用资源换取效率,可以实现真正的并行性。对于高阶Pythoner而言,掌握多进程非常有必要。

这篇文章主要想帮助大家理解Python多进程的运行机制基本概念,并且提供一个较为通用的多线程启动模板

先看一段使用多进程的代码:

import time
from multiprocessing import Process

class Runner(Process):
    def __init__(self, name, lat=1):
        super().__init__()
        self.name = name
        self.latency = lat
    def run(self):
        print('%s running' % self.name)
        time.sleep(self.latency)
        print('%s running end' % self.name)
        
p1 = Runner('p1', lat=1)
p2 = Runner('p2', lat=2)
p3 = Runner('p3', lat=1)
p4 = Runner('p4', lat=4)
p1.start()
p2.start()
p3.start()
p4.start()
print('ok')

咱们开了4个进程,假设要处理4个任务,每个任务需要的延迟时间在lat中定义出来了。对于进程p1-p4而言,只要start()就会启动,然后互相几乎不会影响其他进程的延迟时间。运行结果:

p1 running
p2 running
ok
p3 running
p4 running
p1 running end
p3 running end
p2 running end
p4 running end

这个结果咱们要结合时间戳来看,‘p1 running’、‘p2 running’、‘ok’、‘p3 running’、'p4 running’这4行几乎是同一时间打印出来的。而后面的4个end则都经过了相应的延迟时间之后才打印出来。
我这里想到一个形象化的比喻:4个进程就像4支蜡烛,咱们依次点亮它们,每根蜡烛可以烧[1, 2, 1, 4]个小时,相对于hour级别的燃烧时间,咱们点亮它们所花费的几秒中的时间差可以忽略,我们可以认为它们是同一时间起燃的。于是,前5行几乎是同一时间打印出来。这里需要注意的是,主程序中的"ok"也跟几个进程同时打印出来。所以,这里可以掌握一种sense:对于主程序来讲,进程只管触发一下(如p1.start()),程序会继续往下走,不会等待进程运行结束。

如果我想让主程序等待一下进程结束再运行呢?:那就用join()。
上面代码稍微改动:

import time
from multiprocessing import Process

class Runner(Process):
    def __init__(self, name, lat=1):
        super().__init__()
        self.name = name
        self.latency = lat
    def run(self):
        print('%s running' % self.name)
        time.sleep(self.latency)
        print('%s running end' % self.name)
        
p1 = Runner('p1', lat=1)
p2 = Runner('p2', lat=2)
p3 = Runner('p3', lat=1)
p4 = Runner('p4', lat=4)
p1.start()
p1.join()
p2.start()
p3.start()
p4.start()
p4.join()
print('ok')

只加了2个join(),那么打印顺序会出现怎么样的改变呢?先别急着看输出结果,咱分析一波:p1先start(),但是立马就join()了,阻塞了主程序,那么p2.start()这一行要等p1结束才会运行。等p1运行结束,p2,p3,p4同一时间start,然后p4后面接了一个join(),又会最主程序,那么print(‘ok’)会等待p4结束才会运行。p4需要运行4s,在主程序等待这4秒的过程中,运行时间2秒的p2和运行时间1秒的p3也已经运行完毕,所以p3先结束,其次是p2然后是p4,p4结束才会又进入主程序。听没听懂都点个赞呗~
所以运行结果如下:

p1 running
p1 running end
p2 running
p3 running
p4 running
p3 running end
p2 running end
p4 running end
ok

到这里还有问题,请留言交流~