zoukankan      html  css  js  c++  java
  • 进程笔记(一)

    第一节:进程

    第二节:Python多进程示例

    第三节:Process参数说明

    第四节:获取进程编号

    第五节:多进程带参数的任务

    第六节:进程之间不共享全局变量

    第七节:主进程会等待所有的子进程执行结束再结束

    第八节:Process子类创建子进程

    第九节:进程池

    第十节:进程间通信

    1、进程

    一个正在运行的程序或者软件就是一个进程

    • 操作系统进行资源分配的基本单位
    • 每启动一个进程,操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行
    • 一个程序运行后至少有一个进程
    • 一个进程默认有一个线程
    • 进程里面可以创建多个线程
    • 线程是依附在进程里面的,没有进程就没有线程
    • 真正干活的是线程

    主进程就像是一个集团,集团下面有很多子公司(子进程),集团本身也是一个公司,每个公司真正干活的是不同岗位的员工(线程/多线程)

    2、Python多进程示例

    multi_process.py

    import multiprocessing
    import time
    
    def listen_music():
        for i in range(3):
            print('听音乐......','进程名:%s'%multiprocessing.current_process().name)
            time.sleep(0.2)
    
    def read_book():
        for i in range(3):
            print('看书......','进程名:%s'%multiprocessing.current_process().name)
            time.sleep(0.2)
    
    if __name__ == '__main__':
        # 创建听音乐进程(子进程)
        listen_music_process = multiprocessing.Process(target=listen_music,name='我是听音乐的进程')
        # 创建看书进程 (子进程)
        read_book_process = multiprocessing.Process(target=read_book,name='我是看书的进程')
        # 启动子进程
        listen_music_process.start()
        read_book_process.start()
    

    运行结果

    听音乐...... 进程名:我是听音乐的进程
    看书...... 进程名:我是看书的进程
    听音乐...... 进程名:我是听音乐的进程
    看书...... 进程名:我是看书的进程
    听音乐...... 进程名:我是听音乐的进程
    看书...... 进程名:我是看书的进程
    

    3、Process参数和方法说明

    Process 继承于 BaseProcess

    class BaseProcess(object):
    
        def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
                     *, daemon=None):
    

    参数说明:

    • group:指定进程组,默认为None (官方解释:group 应该始终是 None ;它仅用于兼容 threading.Thread 。 target 是由 run() 方法调用的可调用对象)
    • target:执行的目标任务名(传入函数名字,不是函数调用)
    • name:进程名字 (可以使用该参数指定进程名,multiprocessing.current_process().name 可以获取进程名)
    • args:以元组方式给执行任务传参 (给target指定的函数/方法传参)
    • kwargs:以字典方式给执行任务传参(给target指定的函数/方法传参)

    常⽤⽅法:

    • is_alive():判断进程实例是否还在执⾏;
    • join(self, timeout=None):等待子进程终止 ;
    • start():启动进程实例(创建⼦进程);
    • run():如果没有指定target的任务,对这个对象调⽤start()⽅法时,就将执
      ⾏对象中的run()⽅法;
    • terminate():⽴即终⽌进程;

    4、获取进程编号

    import os
    os.getpid()   表示获取当前进程编号
    os.getppid()  表示获取当前父进程编号
    

    获取进程编号的目的是验证主进程和子进程的关系,可以得知子进程是由那个主进程创建出来的

    multi_process_id.py

    import multiprocessing
    import time
    import os
    
    def listen_music():
    
        # 获取当前进程的编号
        print('listen_music 进程当前编号:',os.getpid())
        # 获取当父进程的编号
        print('listen_music 父程当前编号:',os.getppid())
        for i in range(3):
            print('听音乐......','进程名:%s'%multiprocessing.current_process().name)
            time.sleep(0.2)
    
    def read_book():
    
        # 获取当前进程的编号
        print('read_book 进程当前编号:', os.getpid())
        # 获取当父进程的编号
        print('read_book 父进程当前编号:', os.getppid())
        for i in range(3):
            print('看书......','进程名:%s'%multiprocessing.current_process().name)
            time.sleep(0.2)
    
    if __name__ == '__main__':
        # 获取当前进程的编号
        print("主进程 main 编号:", os.getpid())
    
        # 创建听音乐进程(子进程)
        listen_music_process = multiprocessing.Process(target=listen_music,name='我是听音乐的进程')
        # 创建看书进程 (子进程)
        read_book_process = multiprocessing.Process(target=read_book,name='我是看书的进程')
        # 启动子进程
        listen_music_process.start()
        read_book_process.start()
    

    运行结果

    主进程 main 编号: 2281
    listen_music 进程当前编号: 2283
    listen_music 父程当前编号: 2281
    听音乐...... 进程名:我是听音乐的进程
    read_book 进程当前编号: 2284
    read_book 父进程当前编号: 2281
    看书...... 进程名:我是看书的进程
    听音乐...... 进程名:我是听音乐的进程
    看书...... 进程名:我是看书的进程
    听音乐...... 进程名:我是听音乐的进程
    看书...... 进程名:我是看书的进程
    

    5、多进程带参数的任务

    • args 表示以元组的方式给执行任务传参
    • kwargs 表示以字典方式给执行任务传参

    multi_process_args.py

    import multiprocess
    import time
    
    def task(task_name):
        for i in range(3):
            print('我的任务名:',task_name)
            time.sleep(0.2)
    
    
    if __name__ == '__main__':
        # 任务一:听歌
        task1 = multiprocessing.Process(target=task,args=('听歌...',))
        # 任务二:看书
        task2 = multiprocessing.Process(target=task,kwargs={'task_name':'看书...'})
    
        # 启动任务
        task1.start()
        task2.start()
    

    运行结果

    我的任务名: 听歌...
    我的任务名: 看书...
    我的任务名: 听歌...
    我的任务名: 看书...
    我的任务名: 看书...
    我的任务名: 听歌..
    

    6、进程之间不共享全局变量

    创建子进程会对主进程资源进行拷贝,也就是说子进程是主进程的一个副本,之所以进程之间不共享全局变量,是因为操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已。

    multi_process_global_var.py

    import multiprocessing
    import os
    
    MY_LIST = []
    
    
    def task(task_name):
        print(task_name, '的父进程id:', os.getppid())
        for i in range(3):
            print(i, task_name, '的进程id', os.getpid())
            MY_LIST.append(i)
        print(task_name, ',MY_LIST:', MY_LIST)
    
    
    if __name__ == '__main__':
        print('主进程id:', os.getppid())
        task1 = multiprocessing.Process(target=task, args=('task1',))
        task2 = multiprocessing.Process(target=task, args=('task2',))
        task1.start()
        task2.start()
        task1.join()
        task2.join()
        print('主进程 MY_LIST', MY_LIST)
    
    

    运行结果

    主进程id: 14628
    task2 的父进程id: 1976
    0 task2 的进程id 17040
    1 task2 的进程id 17040
    2 task2 的进程id 17040
    task2 ,MY_LIST: [0, 1, 2]
    task1 的父进程id: 1976
    0 task1 的进程id 16436
    1 task1 的进程id 16436
    2 task1 的进程id 16436
    task1 ,MY_LIST: [0, 1, 2]
    主进程 MY_LIST []
    

    7、主进程会等待所有的子进程执行结束再结束

    孤儿进程

    正常情况下,主进程会等待所有的子进程执行结束再结束,但是如果主进程突然被Kill,剩下的进程就叫做"孤儿进程"

    僵尸进程

    如果子进程在exit()之后,父进程没有来得及处理,那么保留的那段信息就不会释放,其进程号就会一直被占用, 这种进程称为“僵尸进程”

    8、Process子类创建子进程

    Process类 run 方法

    如果没有给定target参数,对这个对象调⽤start()⽅法时,就将执
    ⾏对象中的run()⽅法

    multi_process_run

    import os
    from multiprocessing import Process
    
    
    class MyMultiProcess(Process):
    
        def __init__(self, task_name):
            Process.__init__(self)
            self.task_name = task_name
    
        def run(self):
            for i in range(3):
                print(i, self.task_name, '的进程id', os.getpid(),'---','父进程id:',os.getppid())
    
    
    if __name__ == '__main__':
        print('父进程id:', os.getpid())
        p1 = MyMultiProcess('task1')
        p2 = MyMultiProcess('task2')
        p1.start()
        p2.start()
    

    运行结果

    父进程id: 15292
    0 task1 的进程id 6596 --- 父进程id: 15292
    0 task2 的进程id 12540 --- 父进程id: 15292
    1 task1 的进程id 6596 --- 父进程id: 15292
    1 task2 的进程id 12540 --- 父进程id: 15292
    2 task1 的进程id 6596 --- 父进程id: 15292
    2 task2 的进程id 12540 --- 父进程id: 15292
    

    9、进程池

    进程池用于快速大量生成进程任务,把所有进程任务添加到进程池,进程池有一个同时执行的最大进程数,当任务数量多余设置的最大进程数,那么后面的任务会进入等待,任务先进先出。

    multi_process_pool

    from multiprocessing import Pool
    import os
    
    def task(task_name):
        for i in range(3):
            print(task_name, '的进程id', os.getpid(), '---', '父进程id:', os.getppid())
    
    if __name__ == '__main__':
        # 定义⼀个进程池,最⼤进程数2
        process_pool = Pool(2)
        # 往进程添加任务
        for i in range(3):
            # 非堵塞的方式添加任务
            process_pool.apply_async(func=task,args=('任务%s'%(i+1),))
    
        # 关闭进程池 , 关闭后不再添加新的任务
        process_pool.close()
        process_pool.join()
    

    运行结果

    任务1 的进程id 8624 --- 父进程id: 6372
    任务2 的进程id 17188 --- 父进程id: 6372
    任务1 的进程id 8624 --- 父进程id: 6372
    任务2 的进程id 17188 --- 父进程id: 6372
    任务1 的进程id 8624 --- 父进程id: 6372
    任务2 的进程id 17188 --- 父进程id: 6372
    任务3 的进程id 8624 --- 父进程id: 6372
    任务3 的进程id 8624 --- 父进程id: 6372
    任务3 的进程id 8624 --- 父进程id: 6372  
    

    Pool常⽤方法:

    • apply_async(func, args=(), kwds={}) :使⽤⾮阻塞⽅式调⽤func(并⾏执
      ⾏,堵塞⽅式必须等待上⼀个进程退出才能执⾏下⼀个进程),args为
      传递给func的参数列表,kwds为传递给func的关键字参数列表;
    • apply(func, args=(), kwds={}):使⽤阻塞⽅式调⽤func
    • close():关闭Pool,使其不再接受新的任务;
    • terminate():不管任务是否完成,⽴即终⽌;
    • join():主进程阻塞,等待⼦进程的退出, 必须在close或terminate之后
      使⽤;

    10、进程间通信

    multiprocessing 模块的 Queue 类实现多进程之间的数据传递

    '''

    '''

  • 相关阅读:
    Javaweb学习12.4
    Javaweb学习11.23
    Javaweb学习11.29
    Javaweb学习12.3
    Javaweb学习12.1
    Javaweb学习11.27
    2020年8月25日Java学习日记
    2020年8月18日Java学习日记
    2020年8月22日Java学习日记
    2020年8月21日Java学习日记
  • 原文地址:https://www.cnblogs.com/snailrunning/p/12169209.html
Copyright © 2011-2022 走看看