python 多进程学习

简介与前言

  • 单核CPU执行多任务原理:
  • 操作系统交替轮流执行各个任务。先让任务1执行0.01秒,然后切换到任务2执行0.01秒,再切换到任务3执行0.01秒…这样往复地执行下去。由于cpu的执行速度非常快,所以使用者的主观感受就是这些任务在并行地执行。
  • 多核cpu执行多任务的原理:
  • 由于实际应用中,任务的数量往往远超过cpu的核数,所以操作系统实际上是把这些多任务轮流地调度到每个核心上执行。
  • 对于操作系统来说,一个应用就是一个进程。比如打开一个浏览器,它是一个进程;打开一个记事本,它是一个进程。每个进程有它特定的进程号。他们共享系统的内存资源。
  • 进程是操作系统分配资源的最小单位。
  • 而对于每一个进程而言,比如一个视频播放器,它必须同时播放视频和音频,就至少需要同时运行两个“子任务”,进程内的这些子任务就是通过线程来完成。线程是最小的执行单元。
  • 一个进程它可以包含多个线程,这些线程相互独立,同时又共享进程所拥有的资源。

线程与进程的区别总结

  • 线程共享内存空间;进程的内存是独立的
  • 同一个进程的线程之间可以直接交流;两个进程想通信,必须通过一个中间代理来实现
  • 创建新线程很简单; 创建新进程需要对其父进程进行一次克隆
  • 一个线程可以控制和操作同一进程里的其他线程;但是进程只能操作子进程
  • 改变主线程(如优先权),可能会影响其它线程;改变父进程,不影响子进程

** 进程模块 multiprocessing **

  • python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程
  • multiprocessing是Python提供的一个跨平台的多进程模块,通过它可以很方便地编写多进程程序,在不同的平台(Unix/Linux, Windows)都可以执行
  • multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件
创建单个进程
  • 利用multiprocessing.Process对象可以创建进程

Process介绍
构造方法

  • 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():不管任务是否完成,立即停止工作进程。
    属性
    authkey
  • daemon:和线程的setDeamon功能一样(将父进程设置为守护进程,当父进程结束时,子进程也结束)。
  • exitcode(进程在运行时为None、如果为–N,表示被信号N结束)。
  • name:进程名字。
  • pid:进程号

创建一个进程任务

import multiprocessing
import time

def worker(interval):
    n = 5
    while n > 0:
        print("The time is {0}".format(time.ctime()))
        time.sleep(interval)
        n -= 1

if __name__ == "__main__":
    p = multiprocessing.Process(target = worker, args = (3,))
    p.start()
    print "p.pid:", p.pid
    print "p.name:", p.name
    print "p.is_alive:", p.is_alive()

程序输出:

p.pid: 1896
p.name: Process-1
p.is_alive: True
The time is Mon Feb 18 19:42:49 2019
The time is Mon Feb 18 19:42:52 2019
The time is Mon Feb 18 19:42:55 2019
The time is Mon Feb 18 19:42:58 2019
The time is Mon Feb 18 19:43:01 2019

创建多个进程任务

import multiprocessing
import time

def worker_1(interval):
    print("worker_1")
    time.sleep(interval)
    print("end worker_1")

def worker_2(interval):
    print("worker_2")
    time.sleep(interval)
    print("end worker_2")

def worker_3(interval):
    print("worker_3")
    time.sleep(interval)
    print("end worker_3")

if __name__ == "__main__":
    p1 = multiprocessing.Process(target = worker_1, args = (2,))
    p2 = multiprocessing.Process(target = worker_2, args = (3,))
    p3 = multiprocessing.Process(target = worker_3, args = (4,))

    p1.start()
    p2.start()
    p3.start()

    print("The number of CPU is:" + str(multiprocessing.cpu_count()))
    for p in multiprocessing.active_children():
        print("child   p.name:" + p.name + "\tp.id" + str(p.pid))
    print("END!!!!!!!!!!!!!!!!!")

程序输出

The number of CPU is:8
child   p.name:Process-1        p.id12848
child   p.name:Process-2        p.id4796
child   p.name:Process-3        p.id8988
END!!!!!!!!!!!!!!!!!
worker_1
worker_2
worker_3
end worker_1
end worker_2
end worker_3

将进程定义为类

  • 进程p调用start()时,自动调用run()
import multiprocessing
import time

class ClockProcess(multiprocessing.Process):
    def __init__(self, interval):
        multiprocessing.Process.__init__(self)
        self.interval = interval

    def run(self):
        n = 5
        while n > 0:
            print("the time is {0}".format(time.ctime()))
            time.sleep(self.interval)
            n -= 1

if __name__ == '__main__':
    p = ClockProcess(3)
    p.start()

输出

the time is Mon Feb 18 20:17:20 2019 
the time is Mon Feb 18 20:17:23 2019
the time is Mon Feb 18 20:17:26 2019
the time is Mon Feb 18 20:17:29 2019
the time is Mon Feb 18 20:17:32 2019

join()方法介绍

  • join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。
  • 哪个子进程调用了join方法,主进程就要等该子进程执行完后才能继续向下执行

** 线程模块 threadding **