多进程_篇

什么是一个进程

进程是一个已运行程序的实例

程序与进程的区别

程序是一个死的,进程是一个程序运行在内存中

当创建进程时,子进程是完全复制的父进程(主进程)的

原理; 实例 (不能在Windows上运行)

实例:
# 多进程
# 实现同时执行多个方法
import os

# 任务一   跳舞
import time


def dance():
    # 输出多次
    for i in range(3):
        print('我在跳舞!')
        time.sleep(1)


# 任务二   唱歌
def sing():
    # 输出多次
    for i in range(3):
        print('我在唱歌')
        time.sleep(1)


# 创建多进程
stat = os.fork()
# 判断谁是主进程与子进程   主进程ID大于0
if stat == 0:
    # 调用子进程
    dance()
else:
    # 调用主进程
    sing()

多次fork

# coding=utf-8
import os
import time

# 注意,fork函数,只在Unix/Linux/Mac上运行,windows不可以
pid = os.fork()
if pid == 0:
    print('hello 1')
else:
    print('hello 2')

pid = os.fork()
if pid == 0:
    print('hello 3')
else:
    print('hello 4')

time.sleep(1)

使用类创建多进程 (推荐) 可跨平台运行

需要使用模块 process

实例
import os
import time
from multiprocessing import Process


# 使用类创建一个多进程

def sing():
    # 查看进程id
    print(f'我的进程id是:{os.getpid()}')
    print(f'父进程id是:{os.getppid()}')
    for i in range(3):
        print('我在唱歌')
        time.sleep(1)


def dance():
    # 查看进程id
    print(f'我的进程id是:{os.getpid()}')
    print(f'父进程id是:{os.getppid()}')
    for i in range(3):
        print('我在跳舞')
        time.sleep(1)


# 创建调试方法    (规范)
def main():
    #  创建一个进程对象
    p1 = Process(target=sing)  # 注意: 这里调用方法是不能加括号的
    # 开启进程
    p1.start()

    # 创建一个子进程
    p2 = Process(target=dance)
    # 开启进程
    p2.start()


if __name__ == '__main__':
    main()

运行结果:

两个ospf进程互相引入cost值变化 ospf多进程概念_子进程

创建了两个子进程,一个主进程

进程类参数的传递(Process)

实例:
import time
from multiprocessing import Process

# 参数传递规范   延迟:sleep       循环数:cycle

# 练习参数传递
def sing(sleep, cycle,**kwargs):
    for i in range(cycle):
        print('我在唱歌')
        print(kwargs)		# 打印关键字传参
        time.sleep(sleep)

def dance(sleep, cycle):
    for i in range(cycle):
        print('我在跳舞')
        time.sleep(sleep)

def main():
    # 初始化时间
    time_start = time.time()
    # 创建多进程
    p1 = Process(target=sing, args=(1, 3),kwargs={"kw":'sing'})
    # 开启进程
    p1.start()
    # 创建子进程
    p2 = Process(target=dance, args=(1, 3))
    # 开启进程
    p2.start()

#     等待子进程结束才执行
    p1.join()
    #  当p1结束时再执行后面的
    p2.join()
    print(f'运行时间:{time.time()-time_start}')		# 计算运行时间

#     不管子进程是否运行结束,直接终止子进程
    p1.terminate()
    p2.terminate()

#         在Windows下开发 必须放在main 里面,不然会报错
if __name__ == '__main__':
    main()

当子进程被主进程干掉的时候才会被回收销毁

进程池

什么是进程池?

进程池就是设定几个进程做任务,谁先干完,谁继续换活干。

例如: 公园里的小船,已知的船数量,不同的人去坐,谁先下船,就换人上船

实例:
# 进程池
import os
from multiprocessing import Pool
import time, random


def pool(i):
    print('PID: {}  运行:{}'.format(os.getpid(),i))
    # 随机时间
    time.sleep(random.random() * 2)

p = Pool(3)  # 设置进程池有三个进程
for i in range(10):
    # 调用异步,分配任务
    p.apply_async(pool,(i,))

p.close()       # 不能在添加任务
p.join()        # 等待所有子进程运行结束
print('运行结束')

进程池是解决每一个任务创建一个进程占用内存空间大的问题

进程间通信( 通过队列来实现 )

使用模块:from multiprocessing import Queue

实例:

from multiprocessing import Queue, Process

#  实例   边写边读

# 读
def read(queue):
    while True:
        # 读取一个
        if not queue.empty():
            print(queue.get())
        else:
            #  退出
            break

# 写
def write(queue):
    for i in ['a', 'b', 'c', 'd']:
        # 添加进队列
        queue.put(i)

def main():
    # 创建一个队列
    queue = Queue()
    #         创建一个对象
    p = Process(target=write, args=(queue,))  # 元组传入
    #     启动进程
    p.start()
    # 创建一个对象
    p1 = Process(target=read, args=(queue,))  # 元组传入
    # 开启进程
    p1.start()

补充:

什么是一个僵尸进程:

当子进程死的时候,主进程还在睡,迟迟没有进行对子进程的回收;子进程并没有退出,仍然占用着系统的资源

解决方法,杀死主进程,子进程由1号进程接管

什么是孤儿进程:

当主进程挂掉的时候,子进程还没运行完,此时所有的子进程由1号进程接管,当1号进程接管时,子进程将变为守护进程.

什么是守护进程:

守护进程一班用于服务;一直运行直到系统关闭,只有在任务完成后自动结束