zoukankan      html  css  js  c++  java
  • 进程

    操作系统

    操作系统的定义:
    操作系统是存在于硬件与软件之间,管理,协调,控制软件与硬件的交互.
    操作系统的作用(面试会问)
    1.将一些复杂的硬件操作封装成接口,便于使用.
    2.合理的调度分配多个进程与CPU的关系让其有序化
    如果没有操作系统,你去写一个程序,你只要完成两层即可.
    第一层: 你要学会底层硬件:cpu,内存,磁盘是如何工作使用的.
    第二层: 去调用这些底层的硬件.
    

    进程

    操作系统调度作用,将磁盘上的程序加载到内存,然后交由CPU去处理.一个CPU正在运行的一个程序,就叫开启了一个进程
    进程:正在进行的一个过程或者说一个任务。而负责执行任务则是cpu。
    程序: 一堆静态的文件代码文件
    两者区别:
        1.程序仅仅只是一堆代码而已,而进程指的是程序的运行过程。
        2.进程是动态的,程序是静态的
      
    

    多道技术

    多道技术中的多道指的是多个程序,多道技术的实现是为了解决多个程序竞争或者说共享同一个资源(比如cpu)的有序调度问题,解决方式即多路复用,多路复用分为时间上的复用和空间上的复用。
    
    空间上的复用:将内存分成多个区域,一个内存可以执行多个进程
    时间上的复用:当多个进程抢占一个CPU资源时,操作系统会使进程的执行变得合理有序
    

    并发 和 并行

    串行: 所有的任务一个一个的完成.执行完一个任务,在执行下一个任务
    并发: 一个cpu执行多个进程
    并行: 多个CPU执行多个进程
    阻塞: CPU遇到io就会阻塞
    非阻塞:没有IO,就叫非阻塞.
        
    有效的提高了CPU的效率
    
    

    进程的创建方式

    1.
    from multiprocessing import Process
    import time
    def tasf(name):
        print(f"{name}来了")
        time.sleep(2)
        print(f"{name}走了")
    
    if __name__ == '__main__':                   #在Windows环境下 必须写main 与Windows操作系统有冲突
        p = Process(target=tasf,args=("小宋",))  #创建一个对象进程  args必须是个元祖  target:表示这个进程实例所调用对象;args:表示调用对象的位置参数元组;
    
        p.start()   #只是向操作系统发送一个开辟子进程的信号,然后执行下一行 这个操作系统接收到之后 会从内存中开辟一个子进程空间 然后把主进程的数据copy到子进程空间,开辟子进程的开销是很大的执行一个子进程,永远会先打印主进程
    
    2.
    from multiprocessing import Process
    import time
    class MyProcess(Process):
        def __init__(self,name):
            super().__init__()   #父类中找
            self.name = name
        def run(self): #  如果不是run 回去父类中找,父类中没有run方法,所以就不会执行,所以必须是run
            print(f'{self.name} is running')
            time.sleep(2)
            print(f'{self.name} is gone')
    if __name__ == '__main__':
        p = MyProcess('你')
        p.start()   #会执行一个run方法 类的约束
        print('=====主')
        # 一个py文件是一个主进程
    
    

    验证进程的空间隔离

    #进程之间的数据是隔离的,数据不共享
    from multiprocessing import Process
    n = 100
    def work():
        global n
        n = 0
        print('子进程内:',n)
    if __name__ == '__main__':
        p= Process(target=work)
        p.start()
        p.join()
        print('主进程内:',n)
    子进程内: 0
    主进程内: 100
    #等待子进程执行完后,如果数据是共享的话,子进程就通过global将n改为0,但是通过结果,结果仍是主进程n = 100 子进程n = 0
    # 说明子进程对n 的修改没有在主进程中生效 说明他们之间的数据是隔离的
    

    进程的 p i d

    import os
    print(f'子进程:{os.getpid()}')  #获取子进程id  (Pycharm是主进程)
    print(f'主进程:{os.getppid()}')  #获取主进程id  (Pycharm是主进程)
    

    进程join

    from multiprocessing import Process
    import time
    def task(sec,name):
        print(f'{name}is running')
        time.sleep(sec)
        print(f'{name}is gone')
    if __name__ == '__main__':
        strat_time = time.time()
        p = Process(target=task,args=(3,"你"))
        p1 = Process(target=task,args=(4,"我"))
        p2= Process(target=task,args=(1,"他"))
        p.start()
        p1.start()
        p2.start()
    
        p.join()#执行到这时,睡3秒,由于是并行或并发,在这3秒中会先执行 p2的'他',在执行p的'你' 执行完后执行14782,在执行p1的'我' 时间的合理利用,提高CPU效率
        print(14782)
        p1.join()
        p2.join()
    
        #join执行完之后才执行join下边的代码
        print(f"{time.time()-strat_time}")
        
    ****************************************************************************************************
    对上一个代码的优化
    from multiprocessing import Process
    import time
    def sendmail(n):
        time.sleep(1)
        print(f'发送邮件{n}')
    if __name__ == '__main__':
        l =[]
        for i in range(10):
            p = Process(target=sendmail,args=(i,))
            l.append(p)
            p.start()
        for p in l:
            p.join()
        print('所有的邮件都已经发送了')
        
    ****************************************************************************************************
    from multiprocessing import Process
    import time
    def send(num):
        time.sleep(0.5)
        print(f"发送邮件{num}")
    if __name__ == '__main__':
        for i in range(10):
            p = Process(target=send,args=(i,))
            p.start()
            p.join()
        print('所有的邮件都已经发送了')
    

    守护进程

    主进程创建守护进程
      其一:守护进程会在主进程代码执行结束后就终止
      其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children
    注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止
    
    from multiprocessing import Process
    import time
    def func():
        print(123)
        time.sleep(1)
        print('end123')
    def foo():
        print(456)
        time.sleep(2)
        print('end456')
    if __name__ == '__main__':
        p1 = Process(target=func)
        p2 = Process(target=foo)
        p1.daemon = True #守护进程p1
        p1.start()       #执行p1的子进程时,子进程需要开辟内存空间,需要耗费时间,所以先执行 print('----main----')
                         #所以执行完 print('----main----')之后,子进程将不执行,由于p2没有被守护,所以会执行p2
        p2.start()  
        print('----main----')
        
    ----main----
    456
    end456
    

    进程对象的其他属性

    ********************************************terminate************************************************
    1.
    from multiprocessing import Process
    import time
    def task(name):
        print(f"{name} is running")
        print(f"{name} is gone")
    if __name__ == '__main__':
        p = Process(target=task,args=('常新',),name = 'Alex')
        p.start()
        time.sleep(1)   #睡1秒,足够时间执行子进程中的内容
        p.terminate()   #杀死进程
        p.join()        #当执行完子进程后执行以下的内容
        print(p.name)
    #常新 is running
    #常新 is gone
    #Alex
    
    2.
    from multiprocessing import Process
    import time
    def task(name):
        print(f"{name} is running")
        # time.sleep(2)
        print(f"{name} is gone")
    if __name__ == '__main__':
        p = Process(target=task,args=('常新',),name = 'Alex')
        p.start()
        p.terminate()   #直接杀死子进程
        p.join()
        print(p.name)   #Alex
    
    3.
    from multiprocessing import Process
    import time
    def task(name):
        print(f"{name} is running")
        time.sleep(2)   #睡2秒
        print(f"{name} is gone")
    if __name__ == '__main__':
        p = Process(target=task,args=('常新',),name = 'Alex')
        p.start()
        time.sleep(1)    #睡1秒  先执行子进程的 print(f"{name} is running") 接着执行,发现又睡2秒,但这一步是睡眠1秒,所以向下执行p.terminate() 结束子进程的 print(f"{name} is gone") 
        p.terminate()
        p.join()
        print(p.name)
    #常新 is running
    #Alex
    
     4.
    from multiprocessing import Process
    import time
    def task(name):
        print(f"{name} is running")
        time.sleep(2)   #睡2秒
        print(f"{name} is gone")
    if __name__ == '__main__':
        p = Process(target=task,args=('常新',),name = 'Alex')
        p.start()
        time.sleep(3)    #睡3秒  先执行子进程的 print(f"{name} is running") 在睡眠2秒,此时这步还剩1秒,继续执行子进程的print(f"{name} is gone") 所以没有杀死子进程,子进程就已经执行完了
        p.terminate()
        p.join()
        print(p.name)
    #常新 is running
    #常新 is gone
    #Alex
    
    ********************************************is_alive*************************************************
    
    from multiprocessing import Process
    import time
    import os
    def task(n):
        print(1233)
        time.sleep(5)
        print(f"{n} is running {os.getpid()},{os.getppid()}")
    if __name__ == '__main__':
        p1 = Process(target=task,args=(1,))
        p1.start()
        p1.terminate()   #只是给操作系统发送信号,关闭子进程,交给操作系统,不知道具体什么时候什么时候关闭
        #time.sleep(0.00000000000000000000000001)  #极限时间
        time.sleep(1)    #睡眠1秒,在睡眠1秒过程中,先执行主进程print('主') ,接着执行print(p1.is_alive())
        print("主")
        print(p1.is_alive()) #判断子进程是否还存活 
    #主
    #False
    
    

    僵尸进程和孤儿进程

    主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收
    
    僵尸进程(有害): 所有的子进程结束之后,在被主进程回收之前,都会进入僵尸进程状态
    孤儿进程: 父进程由于某种原因结束了,但是你的子进程还在运行中,这样你的这些子进程就成了孤儿进程.你的父进程如果结束了,你的所有的孤儿进程就会被init进程的回收,init就变成了你的父进程,对你进行回收.
    回收内容:进程号 运行状态 时间
        
    僵尸进程的危害:如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号.
    
    僵尸进程如何解决?
    父进程产生了大量子进程,但是不回收,这样就会形成大量的僵尸进程,解决方式就是直接杀死父进程,将所有的僵尸进程变成孤儿进程进程,由init进行回收.
    
    

    锁和队列

    #文件db的内容为:{"count":1}
    #注意一定要用双引号,不然json无法识别
    #并发运行,效率高,但竞争写同一文件,数据写入错乱
    from multiprocessing import Process,Lock
    import time,json,random
    def search():
        dic=json.load(open('db'))
        print('33[43m剩余票数%s33[0m' %dic['count'])
    
    def get():
        dic=json.load(open('db'))
        time.sleep(0.1) #模拟读数据的网络延迟
        if dic['count'] >0:
            dic['count']-=1
            time.sleep(0.2) #模拟写数据的网络延迟
            json.dump(dic,open('db','w'))
            print('33[43m购票成功33[0m')
    
    def task():
        search()
        get()
    
    if __name__ == '__main__':
        for i in range(100): #模拟并发100个客户端抢票
            p=Process(target=task)
            p.start()
            
    加锁
    #文件db的内容为:{"count":5}
    #注意一定要用双引号,不然json无法识别
    #并发运行,效率高,但竞争写同一文件,数据写入错乱
    from multiprocessing import Process,Lock
    import time,json,random
    def search():
        dic=json.load(open('db'))
        print('33[43m剩余票数%s33[0m' %dic['count'])
    
    def get():
        dic=json.load(open('db'))
        time.sleep(random.random()) #模拟读数据的网络延迟
        if dic['count'] >0:
            dic['count']-=1
            time.sleep(random.random()) #模拟写数据的网络延迟
            json.dump(dic,open('db','w'))
            print('33[32m购票成功33[0m')
        else:
            print('33[31m购票失败33[0m')
    
    def task(lock):
        search()
        lock.acquire()
        get()
        lock.release()
    
    if __name__ == '__main__':
        lock = Lock()
        for i in range(100): #模拟并发100个客户端抢票
            p=Process(target=task,args=(lock,))
            p.start()
    #加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。
    
    
    ***队列***
    什么是队列? ---> 队列就是存在于内存中的一个容器,它的一个特点:队列的特性就是FIFO,完全支持先进先出的原则 进程批次之间互相隔离,要实现进程间通信(IPC),multiprocessing模块中的队列方式可以实现
    创建队列的类(底层就是一管道和锁定的方式实现) Queue([maxsize]) : 创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实多进程之间的数据传递
        
    from multiprocessing import Queue
    q = Queue(3)
    q.put(1)
    q.put(2)
    q.put(3)      # q.put(4) # 当队列数据已经达到上限,再插入数据的时候,程序就会阻塞住
    print(q.get()) 
    print(q.get()) 
    print(q.get()) 
    print(q.get()) # 当队列中的数据取完之后,程序也会阻塞住
    
    maxsize() q = Queue(3) 数据量不易过大,队列主要存放精简的重要的数据 
    block 默认值是True,当你插入的数据量超过大限度,默认阻塞,如果block = False 数据超过大限度,不阻塞了 直接报错. timeout = 3 延时报错,超过3秒再不put数据,就会报
    
    # 用进程通信队列模拟实例 
    from multiprocessing import Process from multiprocessing import Queue import os
    def task(q):
        try:
            q.put(f'{os.getpid()}',block=False)
        except Exception:
            return
    if __name__ == '__main__':
        q = Queue(10)
        for i in range(100):
            p = Process(target=task,args=(q,))# 给CPU发送命令,开启子进程会有一定时间的延迟,在这个时间段内,主进程会继续执行  
            p.start()
        for i in range(1,11):  # 如果循环次数再多,会取到更多的值        				
            print(f'排名为{i}的用户:{q.get()}')
    

    生产者与消费者模型

    生产者  消费者  队列    为了平衡
    如果没有容器,生产者与消费者增强耦合性,不合理.所以要有一个容器,缓冲区,平衡生产力和消费力. 
    from multiprocessing import Process,Queue
    import time,random,os
    def scz(q):
        for i in range(1,6):
            time.sleep(random.randint(1,3))
            res = f'第{i}个包子'
            q.put(res)
            print(f'{os.getppid()}生产了{res}')
    def xfz(q):
        while 1:
            try:
                food = q.get(timeout=3)
                time.sleep(random.randint(1,2))
                print(f"{os.getpid()}吃了{food}")
            except Exception:
                return
    if __name__ == '__main__':
        q = Queue()
        p = Process(target=scz,args=(q,))
        p1 = Process(target=xfz,args=(q,))
        p.start()
        p1.start()
    
  • 相关阅读:
    IDEA 工具 破解码
    postman 使用 及断言
    MonkeyTest 命名
    Jmeter 测试单元的封装与复用
    开发性能测试工具——自己动手实现迭代功能
    jemter安装mysql数据驱动JDBC
    全链路性能测试知识点整理
    Java接口全链路优化:如何降低接口RT时长(转)
    测试自动化之Mock服务思路探讨
    算法分析与设计(一)时间与空间复杂度
  • 原文地址:https://www.cnblogs.com/tangjian219/p/11414405.html
Copyright © 2011-2022 走看看