一、上节回顾

开启进程:

from multiprocessing import Process
import time
def task(name):
    print("%s is running"%name)
    time.sleep(2)
    print("%s is stopping"%name)
if __name__=="__main__":#在windows系统下,开启子进程必须写到这一行下面
    p=Process(target=task,args=("egon",))
    p.start() #只是在给操作系统发了一个信号,让操作系统去开启进程(申请内存+拷贝父进程的地址空间)
    print("")

1、什么是进程?

  进程是一个抽象的概念,进程即正在执行的过程,进程的概念起源于操作系统,

  进程的创建,调度管理都贵操作系统管

2、操作系统的作用?

  1、管理的硬件,把复杂丑陋的硬件接口封装成良好的接口给客户使用

  2、进程的创建,调度管理都贵操作系统管理

3、多道技术?

  产生背景:针对单核下实现并发

  核心:

    1、空间上复用(多个进程的内存空间是互相隔离的)

    2、时间上的复用(复用cpu的时间)

 

一些小知识:

     cpu 时间片是指的cpu中的一小块时间

  作业讲解中遇到的问题:

  (1)并发是指的任务

  (2)实现服务端的并发

  (3)服务端的作用:建立连接 通信

  (4)开启进程:

  (5)listen是指的操作系统的限制,队列是占用的内存的空间

    第一次握手是指的操作系统从从队列中取走一个回给客户端

  (6)操作系统不仅干TCP建立连接的活,还要做其他的工作

  (7)一个server对象产生一个端口建立连接

  (8)一个服务端于多个客户端实现并发

  (9)进程的开启,是占用内存空间,不可能无限的开启进程,客户端有可能会开启一个上百万的进程

二、新内容

(一、开启进程)

 1、进程的两种方式

# # 方式一
from multiprocessing import Process
import time
def task(name):
    print("%s is running"%name)
    time.sleep(2)
    print("%s is stopping"%name)
if __name__=="__main__":#在windows系统下,开启子进程必须写到这一行下面
    p=Process(target=task,args=("egon",))
    p.start() #只是在给操作系统发了一个信号,让操作系统去开启进程(申请内存+拷贝父进程的地址空间)
    print("")
开启进程的方式一
 方式二(不重要,不符合规范)
from multiprocessing import Process
import time
class Myprocess(Process):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):
        time.sleep(2)
        print("%s is running"%self.name)
        time.sleep(3)
if __name__=="__main__":
    p=Myprocess("egon")
    p.start()
    print("")
开启进程的方式二

2、python解释器相当于一个函数,将写的代码编程能运行的程序

  一个程序运行两遍就是两个进程,就相当于一个py关掉又运行了一次(讲特性(线程)的时候会用到)

import time,os
print(os.getpid(),os.getpid())
time.sleep(10)

#python3 test.py----->python.exe

3、僵尸进程:父进程,结束进程还存在

      正常存在是先是子进程结束,然后结束父进程

  重要点:start  join

      确定子进程结束之后才会进行主进程  使用join()

      开启进程的方法 p.start()  只是传递信号给操系统,并没有顺序

      没有办法实现顺序执行

from multiprocessing import Process
import time
def task(name):
    print("%s is running"%name)
    time.sleep(2)
if __name__=="__main__":
    p1=Process(target=task,args=("egon",))
    p2=Process(target=task,args=("alex",))
    p3=Process(target=task,args=("yxxx",))
    p_1=[p1,p2,p3]
    for p in p_1:
        p.start()
    for p in p_1:
        p.join()
    print("")
开启先开启子进程后主进程

4、作为了解

from multiprocessing import Process
import time
def task(name):
    print("%s is running"%name)
    time.sleep(2)
if __name__=="__main__":
    p1=Process(target=task,args=("egon",),name="xxxxx")
    p1.start()
    print(p1.name)
    print(p1.pid)  #子进程 ID
    p1.join()     #先子进程后主进程
    p1.terminate()  #强行终止子进程
    print(p1.is_alive()) #判断子进程是否还存在
    print("")
View Code

 5、参数介绍

1 group参数未使用,值始终为None
2 
3 target表示调用对象,即子进程要执行的任务
4 
5 args表示调用对象的位置参数元组,args=(1,2,'egon',)
6 
7 kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
8 
9 name为子进程的名称

 方法介绍:

1 p.start():启动进程,并调用该子进程中的p.run() 
 2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法  
 3 
 4 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
 5 p.is_alive():如果p仍然运行,返回True
 6 
 7 p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程  

  属性介绍:

1 p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
2 
3 p.name:进程的名称
4 
5 p.pid:进程的pid
6 
7 p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
8 
9 p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)

(二、进程池)

提交/调用任务的方式有两种:

  同步调用:提交/调用一个任务,然后就在原地等着,等到该任务执行完毕拿到结果,再执行下一行代码

  异步调用:提交/调用一个任务,不在原地等着,直接执行下一行代码,结果?

1、异步调用

# from multiprocessing import Process,pool
from concurrent.futures import ProcessPoolExecutor
import time,random,os
def piao(name):
    print("%s is piaoing %s"%(name,os.getpid()))
    time.sleep(random.randint(1,4))

if __name__=="__main__":
    p=ProcessPoolExecutor(4)
    for i in range(10):
        p.submit(piao,"alex %s"%i)

    #关门+等
    #pool.close()
    #pool.join()
    p.shutdown(wait=True)
    print("",os.getpid())
异步调用

说明:

同时进行的进程一共有四个,四个同时进行(一共造出四个进程,就是有四个ID)

for循环丢进进程只是发出一个信号

2、同步调取结果:

3、异步调取结果

# from multiprocessing import Process,pool
from concurrent.futures import ProcessPoolExecutor
import time,random,os
def piao(name,n):
    print("%s is piaoing %s"%(name,os.getpid()))
    time.sleep(1)
    return n ** 2

if __name__ == '__main__':
    p=ProcessPoolExecutor(4)
    objs=[]
    start=time.time()
    for i in range(10):
        # res=p.submit(piao,'alex %s' %i,i).result() #同步调用
        # print(res)
        obj=p.submit(piao,'alex %s' %i,i) #异步调用
        objs.append(obj)

    for obj in objs:
        print(obj.result())

    stop=time.time()
    print(stop-start)
    # 关门+等
    # pool.close()
    # pool.join()
    p.shutdown(wait=True)
    print('',os.getpid())
异步调取结果

异步调取结果不影响并发的执行:

4、时间的计算:开启进程也需要花费时间,切换的时间,操作系统创建进程申请拷贝空间的时间

  开启进程数量越多花费的时间越短(在机器可承受的范围之内的情况下)

from multiprocessing import Process
import time,random,os
def piao(name,n):
    print("%s is piaoing %s"%(name,os.getpid()))
    time.sleep(1)
    return n**2
if __name__=="__main__":
    start=time.time()
    p_1=[]
    for i in range(10):
        p=Process(target=piao,args=("ss",1))
        p_1.append(p)
        p.start()
        
    for p in p_1:
        p.join()
        
    stop=time.time()
    print(stop-start)
时间的计算