高效编程——多进程

多进程

一、多任务原理

  • 概念

    现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统

  • 什么叫多任务?

    就是操作系统可以同时运行多个任务

  • 单核CPU实现多任务原理

    操作系统轮流让各个任务交替执行,QQ执行2us(微秒),切换到微信,在执行2us,再切换到陌陌,执行2us……。表面是看,每个任务反复执行下去,但是CPU调度执行速度太快了,导致我们感觉就像所有任务都在同时执行一样
    image

  • 多核CPU实现多任务原理

    真正的秉性执行多任务只能在多核CPU上实现,但是由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行
    image

  • 并发与并行

    • 并发

      CPU调度执行速度太快了,看上去一起执行,任务数多于CPU核心数

    • 并行

      真正一起执行,任务数小于等于CPU核心数

    • 并发是逻辑上的同时发生,并行更多是侧重于物理上的同时发生。

  • 实现多任务的方式

    • 多进程模式

      启动多个进程,每个进程虽然只有一个线程,但是多个进程可以一起执行多个任务

    • 多线程模式

      启动一个进程,在一个进程的内部启动多个线程,这样多个线程也可以一起执行多个任务

    • 多进程+多线程

      启动多个进程,每个进程再启动多个线程

    • 协程

    • 多进程+协程

二、进程

1、概念

  • 什么是进程?

    是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

  • 对于操作系统

    一个任务就是一个进程。比方说打开浏览器就是启动一个浏览器的进程,在打开一个记事本就启动一个记事本进程,如果打开两个记事本就启动两个记事本进程

2、使用进程

单进程现象

需要等待代码执行完后再执行下一段代码

import time

def run1():
    while 1:
        print("lucky is a good man")
        time.sleep(1)

def run2():
    while 1:
        print("lucky is a nice man")
        time.sleep(1)

if __name__ == "__main__":
    run1()
    # 不会执行run2()函数,只有上面的run1()结束才能执行run2()
    run2()
  • 启动进程实现多任务

    • multiprocessing模块

      跨平台的多进程模块,提供了一个Process类用来实例化一个进程对象

    • Process类

      作用:创建进程(子进程)

    • __name__

    • 这是 Windows 上多进程的实现问题。在 Windows 上,子进程会自动 import 启动它的这个文件,而在 import 的时候是会执行这些语句的。如果你这么写的话就会无限递归创建子进程报错。所以必须把创建子进程的部分用那个 if 判断保护起来,import 的时候 __name__ 不是 __main__ ,就不会递归运行了。

      参数 说明
      target 指定进程执行的任务
      args 给进程函数传递的参数,是一个元组

      注意:此时进程被创建,但是不会启动进程执行

    • 启动进程实现多任务

      from multiprocessing import Process

      创建子进程

      P = Process(target=run,args=(“nice”,),name=‘当前进程名称’)

      • target指定 子进程运行的函数

      • args 指定传递的参数 , 是元组类型

      • 启动进程:Process对象.start()

      获取进程信息

      • os.getpid() 获取当前进程id号
      • os.getppid() 获取当前进程的父进程id号
      • multiprocessing.current_process().name 获取当前进程名称

      父子进程的先后顺序

      • 默认 父进程的结束不能影响子进程 让父进程等待子进程结束再执行父进程

      • p.join() 阻塞当前进程,直到调用join方法的那个进程执行完,再继续执行当前进程。

      • 全局变量在过个进程中不能共享

        注意: 在子进程中修改全局变量时对父进程中的全局变量没有影响

    • 示例代码
import time

from multiprocessing import Process

def run1(name):
    while 1:
        print("%s is a good man"%name)
        time.sleep(1)

def run2():
    while 1:
        print("lucky is a nice man")
        time.sleep(1)

if __name__ == "__main__":
    # 程序启动时的进程称为主进程(父进程)

    # 创建进程并启动
    p = Process(target=run1, args=("lucky",))
    p.start()

    # 主进程执行run2()函数
    run2()
  • 主进程负责调度
    主进程主要做的是调度相关的工作,一般不负责具体业务逻辑
import time
from multiprocessing import Process

def run1():
    for i in range(7):
        print("lucky is a good man")
        time.sleep(1)

def run2(name, word):
    for i in range(5):
        print("%s is a %s man"%(name, word))
        time.sleep(1)

if __name__ == "__main__":
    t1 = time.time()

    # 创建两个进程分别执行run1、run2
    p1 = Process(target=run1)
    p2 = Process(target=run2, args=("lucky", "cool"))

    # 启动两个进程
    p1.start()
    p2.start()

    # 查看耗时
    t2 = time.time()
    print("耗时:%.2f"%(t2-t1))
  • 父子进程的先后顺序
    主进程的结束不能影响子进程,所以可以等待子进程的结束再结束主进程,等待子进程结束,才能继续运行主进程
    p.join() 阻塞当前进程,直到调用join方法的那个进程执行完,再继续执行当前进程。
import time
from multiprocessing import Process

def run1():
    for i in range(7):
        print("lucky is a good man")
        time.sleep(1)

def run2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逐梦舞者

你的打赏是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值