• 并发编程之多进程篇之三


    基于多进程实现并发的套接字通信和守护进程

      一、关于进程之间内存的空间隔离

        看以下的两个实例,比较一下区别:

        实例一: 

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    from multiprocessing import Process
    '''
    a = 66
    def revise():
        global a
        a = 99
        print('修改后的值:a=%d'%a)
    if __name__ == '__main__':
        revise()
        print('全局的值a=%d'%a)'''
    
    '''输出的结果:
    修改后的值:a=99
    全局的值a=99

        实例二: 

    # 证明进程之间内存的空间隔离,各进程之间并不会相互影响
    n = 100
    def talk():
        global n
        n = 1
        print('子进程修改设置:%d '%n)
    
    if __name__ == '__main__':
        p = Process(target=talk)
        p.start() # 只是发送执行信号,并非立即执行
        p.join() # 只有p进程运行结束,才会运行其他进程
    
        print('main:%d'%n)
    '''未加p.join()时:
    main:100
    子进程修改设置:1 
    
    # 添加p.join()后:
    子进程修改设置:1 
    main:100
    '''

      由实例一和实例二可知:不同进程之间存在空间上的隔离,不会相互影响。

      二、多进程通信

        多进程通信以实例方式呈现,分为客户端和服务端。

        客户端.py   

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    from socket import *
    
    client = socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',3306))
    
    while True:
        msg = input('>>>:').strip()
        if not msg:continue
        client.send(msg.encode('utf-8'))
        data = client.recv(1024)
        print('from server:',data.decode('utf-8'))
    
    client.close()
    View Code

        服务端.py 

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    # 多进程并发通信
    from socket import *
    from multiprocessing import Process
    
    def talk(conn):
        while True:
            try:
                data = conn.recv(1024)
                if not data: break
                print('from client:',data.decode('utf-8'))
                conn.send(data.title())
            except  ConnectionResetError:
                break
        conn.close()
    
    def server(ip,port):
        server = socket(AF_INET, SOCK_STREAM)
        server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    
        server.bind((ip,port ))
        server.listen(5)
        while True:
            conn,addres = server.accept()
            p =  Process(target=talk,args=(conn,))
            p.start()
        server.close()
    if __name__ == '__main__':
        server('127.0.0.1',3306)
    View Code

      

      三、join方法的练习 

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    from multiprocessing import Process
    import time
    import random
    
    def task(n):
        time.sleep(random.randint(1,2))
        print('-----%s------'%n)
    
    if __name__ == '__main__':
        p1 = Process(target=task,args=(1,))
        p2 = Process(target=task,args=(2,))
        p3 = Process(target=task,args=(3,))
        p4 = Process(target=task,args=(4,))

      问题1:保证优先运行进程4 

        p4.start()
        p4.join()
        p1.start()
        p2.start()
        p3.start()
    
    #注意,放在if__name__=='__main__':下执行
        '''此时,保证优先运行进程4,并输出
        -----4------
        -----3------
        -----2------
        -----1------
        '''
    View Code

      问题2:保证按进程1、2、3、4顺序执行

        p1.start()
        p1.join()
        p2.start()
        p2.join()
        p3.start()
        p3.join()
        p4.start()
        p4.join()
    
    #同样放在if __name__ == '__main__':下运行
        '''此时保证按顺序输出
        -----1------
        -----2------
        -----3------
        -----4------   
        '''
    View Code

      

      四、守护进程

        1、理解:主进程创建子进程,然后将该进程设置成守护自己的进程,守护进程就好比崇祯皇帝身边的老太监,

        崇祯皇帝已死老太监就跟着殉葬了。

        2、注意:

          1️⃣:守护进程会在主进程代码执行结束后就终止;

          2️⃣:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children。

          如果我们有两个任务需要并发执行,那么开一个主进程和一个子进程分别去执行就ok了,如果子进程的任务在主进程任务结束后就没有存在的必要了,

        那么该子进程应该在开启前就被设置成守护进程。主进程代码运行结束,守护进程随即终止。

        3、实例: 

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    from multiprocessing import Process
    import time
    def task(name):
        print('%s is running'%name)
        time.sleep(2)
        # p = Process(target=task,args=('进程2',))
        # p.start() 会报错--> 'daemonic processes are not allowed to have children' 守护进程不允许再有子进程
    if __name__ == '__main__':
        p = Process(target=task,args=('进程1',))
        p.daemon = True  # --->>  daemon表示守护进程,必须在进程启动前设置,在主进程结束后,也接着死亡
        p.start()
        p.join()
        print('主进程')
    '''
    进程1 is running
    主进程
    '''

        4、关于守护进程的练习,思考执行的结果是怎样的?

    import time
    from multiprocessing import Process
    def fun1():
        print(666)
        time.sleep(1)
        print('----fun1-----')
    def fun2():
        print(888)
        time.sleep(2)
        print('----fun2-----')
    if __name__ == '__main__':
        p1 = Process(target=fun1)
        p2 = Process(target=fun2)
    
        p1.daemon = True
        p1.start()
        p2.start()
        print('----main----')

      答案:

    ----main----
    888
    ----fun2-----
    View Code

        

  • 相关阅读:
    php 安装shpinx扩展
    sphinx 配置实例
    java系统监控分析Jprofile下载及安装配置【转】
    Java监控工具介绍,VisualVm ,JProfiler,Perfino,Yourkit,Perf4J,JProbe,Java微基准测试【转】
    Java虚拟机性能管理神器
    Java虚拟机性能管理神器
    Java虚拟机性能管理神器
    Java虚拟机性能管理神器
    Java虚拟机性能管理神器
    jvisualvm图解【转】
  • 原文地址:https://www.cnblogs.com/schut/p/9011466.html
Copyright © 2020-2023  润新知