Process 进程

一. 多任务

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

二. 单核CPU实现多任务的原理

操作系统轮流让多个任务交替执行 比如QQ执行了2us ,在切换到微信 执行了2us,在切换到其他,表面看起来像是在同时执行,是因为cpu的调度太快

三. 多核cpu实现多任务的原理

如果任务量多于核心数依然是让多个任务去交替执行

(1)并发

看起来像是同时执行 其实还是cpu去调度

(2) 并行

真正的一起执行 任务量 小于等于cpu的核心数

注意: 并发是逻辑上的同时执行,并行是物理上的同时执行

四. 进程模块Process

(1) 单进程

一个代码执行完毕 需要等待下一个代码执行完 在继续往下执行

(2) 实现多进程

__name__ 是windows 上实现多进程的方式 以防止模块被导入 造成多个进程执行的混乱

(3) 开启多进程

from multiprocessing import Process

创建子进程

p = Process(target=函数名)

target 执行子任务的函数名称

(4) 进程等待

默认是主进程 继续往下执行 执行完毕结束

主进程等待子进程

进程名.join()

当子进程执行完毕 主进程继续执行

五. 进程池

当启动大量进程的时候 使用进程池

from multiprocessing import Pool

创建进程池

pool = Pool([进程并发数量]) # 当不传参的时候 并发数为核心数

创建子进程 放入进程池 统一管理

apply_async(func,args=(参数,)) # 并发执行 非阻塞模式

apply(func,args=(参数,)) # 非并发执行 阻塞模式

pool.close() # 进程池关闭 代表 不在向进程池加入子进程

pool.join() # 主进程等待子进程 执行完毕在此执行

注意:

进程池:调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool, join函数等待所有子进程结束

获取子进程的返回值

def demo(x):
    # print(x)
    # time.sleep(2)
    return x  # 将出入进来的参数进行返回
if __name__ == '__main__':
    print(cpu_count())  # 4
    pool = Pool()
    for i in range(10):
        res = pool.apply_async(demo, args=(i,))
        print(res)  # 返回结果对象,此刻并发变成了阻塞一个一个执行
        print(res.get())  # 获取返回值
        # res = pool.apply(demo, args=(i,))
        # print(res)  # 直接返回结果
    pool.close()  # 不在向进程池放进程
    pool.join()  # 进程等待

map方法

如果有大量的数据添加到进程池里 如果使用map会非常的方便

第一个参数传入方法 第二个方法传入列表

实例:

def demo(x):
    time.sleep(2)
    print(x)
if __name__ == '__main__':
    pool = Pool()
    urlList = ['http://www.baidu.com','http://www.taobao.com']
    pool.map(demo,urlList)  # 并发执行

六. 进程通信之 队列

from multiprocessing import Queue

# 创建队列
que= Queue()
# 压入数据
que.put()
# 获取数据
que.get(block=True)  # block默认为True 阻塞一直等待 传入False 非阻塞模式 若为空 会抛出异常
# 队列常用函数
que.empty()  # 判断队列是否为空 返回bool
进程名.terminate()  # 强制终止子进程

注意: 给子进程终止法方法不应该存在 子进程名.join() 因为主进程一直会等待,终止子进程的方法不会被执行

p.daemon = True # 设置子进程 随着主进程结束而结束

七. 自定义进程类

实例:

class MyClass(Process):
    def __init__(self,arg):
        Process.__init__(self) 
       self.arg = arg
    def run(self):
        print(self.arg)  # 调用类的属性
        print("走了")
if __name__ == '__main__': 
   pro = MyClass()
    pro.start()  # 会自动调用run方法

注意:

  1. 只有__init__和run方法 可以重写 但是init需要调用父类的初始化方法
  2. 将当前的自定义类实例化后调用start方法 会自动调用run方法
  3. 如果开启多个子进程需要将当前自定义类多次实例化

猜你喜欢

转载自blog.csdn.net/zuggs_/article/details/81941125