zoukankan      html  css  js  c++  java
  • 并发编程(进程)——创建进程的两种方式,进程间数据相互隔离,进程调度,僵尸进程与孤儿进程,进程对象及其他方法,守护进程,互斥锁,队列介绍,IPC机制(进程间通信)

    一、创建进程的两种方式

    #第一种
    from multiprocessing import Process
    import time
    
    
    def task(n):
        print('我是子进程')
        time.sleep(n)
        print('子进程结束')
    
    
    if __name__ == '__main__':
        # args=(), kwargs={}
        # t=Process(task,args=(1,))
        t = Process(target=task, kwargs={'n': 1})
        t.start()  # 通知操作系统,开启进程,执行task函数
        print('')
    
    #第二种:
    from multiprocessing import Process
    import time
    
    class Task(Process):
        def __init__(self, n):
            super().__init__()
            self.n = n
    
        def run(self):
            print('我是子进程')
            time.sleep(self.n)
            print('子进程结束')
    
    
    if __name__ == '__main__':
        t = Task(1)
        # t.run(1)  # 不是调用t.run(),而是调用t.start()
        t.start()
        print('')

    二、进程间数据相互隔离

    #进程之间数据隔离
    from multiprocessing import Process
    import time
    
    age = 18
    
    
    def task(n):
        global age  # 局部修改全局
        age = 99
        print('我是子进程')
        time.sleep(n)
        print('子进程结束')
        print(age)
    
    
    if __name__ == '__main__':
        t = Process(target=task, kwargs={'n': 1})
        t.start()
        t.join()  # 等待t子进程执行完成
        print('')
        print(age) # 数据没有变,主进程中打印age和子进程的age没有半毛钱关系,数据是隔离的

    三、进程调度

     1 先来先服务(对长作业有利,对短作业无益)
    2 短作业优先(对短作业有利,对长作业无益)
    3 时间片轮转
    4 多级反馈队列

    四、僵尸进程与孤儿进程

    1 僵尸进程:进程结束了,资源还没来得及回收
    2 孤儿进程:主进程挂了,子进程还没结束,它就会被专门的进程接管

    五、进程对象及其他方法

    1 windows:tasklist |findstr 进程id号
    2 mac,Linux:ps aux | grep 进程id号
    3 进程对象:t=Process(target=task, )或者是在进程内部:current_process()
    4 t.pid或者current_process().pid 获取进程id号
    5 os.getpid() 同上,获取进程id号
    6 os.getppid() 获取父进程id号,子进程中获取父进程id,等于父进程的id号
    7 t.is_alive()或者current_process().is_alive() 查看进程是否存活
    8 t.terminate() 关闭进程,在主进程关闭
    from multiprocessing import Process,current_process
    import time
    import os
    
    # 每个进程都会有自己的id号pid
    
    def task():
        print('子进程')
    
        # 当前进程的id号
        print(current_process().pid)
        print(os.getpid()) # 跟上面打印出来是一模一样的
        # 取出该进程父id号
        print('-----',os.getppid())
        # current_process()当前进程对象
    
        print(current_process().is_alive())
        time.sleep(2)
    
        print('子进程结束')
    
    
    if __name__ == '__main__':
        t = Process(target=task, )
        t.start()
        # t1 = Process(target=task, )
        # t1.start()
        # t.is_alive()  # t这个进程是否存活
        # print('主进程打印的结果',t.is_alive())
        print(t.pid)
        time.sleep(0.5)
        # t.terminate()  # 把t进程关闭
        # time.sleep(0.1)
        print('主进程打印的结果', t.is_alive())

    六、守护进程

    from multiprocessing import Process, current_process
    import time
    import os
    
    
    def task():
        # print(os.getpid())
        print('子进程')
        time.sleep(200)
        print('子进程结束')
    
    
    if __name__ == '__main__':
        t = Process(target=task, )
        # 守护进程:主进程一旦结束,子进程也结束
        # t.daemon=True  # 一定要加在启动之前
        t.start()
    
        time.sleep(1)
        print('主进程结束')
        print(os.getppid())
        time.sleep(100)
    
    
    # 问题1 :主进程的父进程是谁? 
    答案:就是pycharm
    
    # 问题2 :主进程开了很多子进程,每个都需要设置守护吗?
    答案:看你的需求,你想让某个进程是守护:t.daemon=True

    七、互斥锁

    同时只有一个人能拿到,必须释放,其他人才能再次获取到
    from multiprocessing import Process, Lock
    import json
    import time
    import random
    
    
    def search():
        # 查票的函数
        # 打开文件,读出ticket_count
        with open('ticket', 'r', encoding='utf-8') as f:
            dic = json.load(f)
            print('余票还有:', dic.get('ticket_count'))
    
    
    def buy():
        with open('ticket', 'r', encoding='utf-8') as f:
            dic = json.load(f)
    
        time.sleep(random.randint(1, 3))  # 模拟一下网络延迟
        if dic.get('ticket_count') > 0:
            # 能够买票
            dic['ticket_count'] -= 1
            # 保存到文件中去
            with open('ticket', 'w', encoding='utf-8') as f:
                json.dump(dic, f)
                print('买票成功')
        else:
            # 买票失败
            print('买票失败')
    
    
    # 写一个函数,先查票,再买票
    
    def task(mutex):
        search()
        # 买票过程要加锁
        # 买前加锁
        # mutex.acquire()
        # buy()  # 10个进程变成了串行执行
        # # 买后释放锁
        # mutex.release()
        with mutex:
            buy()
    
    
    if __name__ == '__main__':
        # 锁的创建,在哪?主进程创建锁
        mutex = Lock()  # 创建一把锁
        # 模拟十个人买票(开10个进程)
        for i in range(10):
            t = Process(target=task, args=(mutex,))
            t.start()
    
    # 面向对象高级:魔法方法(__开头的),__enter__和__exit__,上下文管理器
    # 自己写一个类,实现类似于打开文件 with open 的功能
    # with MyClass('文件名','方式','编码')  as f:
    #     f.read()
    
    
    #在这写代码,f就关闭了

    接上面问题  补充:

    魔法方法之:__inter__  __exit__

    class MyClass():
        def __init__(self,file_name,mode,encoding):
            self.file_name=file_name
            self.mode=mode
            self.encoding=encoding
    
        def __enter__(self):
            print('只要有with,就会执行我')
            self.file=open(self.file_name,self.mode,encoding=self.encoding)
    
            return self.file
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            # 只要顶格写代码,就会执行我
            print('只要顶格写代码,就会执行我')
            self.file.close()
    
    
    with MyClass('ticket','r','utf-8') as f:
        print(f.read())
        print('xxss')
        print("sdfadasf")
    
    
    # a=MyClass('ticket','r','utf-8')#这样做不会打印__enter__里的内容

    八、队列介绍

    from multiprocessing import Queue
    
    # 实例化得到要给对象
    
    q=Queue(5)  # 默认很大,可以放很多,写了个5,只能放5个
    
    # 往管道中放值
    q.put(1)
    q.put('lqz')
    q.put(18)
    q.put(19)
    # q.put(20)
    # q.put(21)
    # q.put_nowait(100)
    
    # 从管道中取值
    # print(q.get())
    # print(q.get())
    # print(q.get())
    # print(q.get(timeout=100))  # 等0.1s还没有值,就结束
    # print(q.get_nowait())        # 不等了,有就是有,没有就没有
    
    print(q.empty())  # 看一下队列是不是空的
    print(q.full())   # 看一下队列是不是满的
    q=Queue(队列大小)
    # 放值
    q.put(asdf)
    q.put_nowait(asdf) # 队列满了,放不进去就不放了,报错

    # 取值
    q.get() # 从队列头部取出一个值
    q.get_nowait() # 从队列头部取值,没有就抛错


    # 队列是否为空,是否满
    print(q.empty()) # 看一下队列是不是空的
    print(q.full()) # 看一下队列是不是满的

    九、IPC机制(进程间通信)

    Inter-Process Communication,进程间通信
    from multiprocessing import Process, current_process, Queue
    import time
    import os
    
    
    def task1(q):
        print('我是task1进程,我的id号是:%s'%os.getpid())
        q.put('lqz is handsome')
    
    
    def task2(q):
    
        # res=q.get()
        # print('我是task2进程,我的id号是:%s'%os.getpid(),res)
        print('我是task2进程,我的id号是:%s'%os.getpid())
    
    
    if __name__ == '__main__':
        q = Queue(5)
    
        t1 = Process(target=task1, args=(q,))
        t1.start()
        t2 = Process(target=task2, args=(q,))
        t2.start()
    
        print(q.get())
    ---37---
  • 相关阅读:
    一些牛逼的统计SQL
    一个有趣的 SQL 查询(查询7天连续登陆)
    Highcharts-3.0.6
    linux 下载并安装Memcache服务器端
    nginx + tomcat集群和动静资源分离
    C#中使用SendMessage在进程间传递数据的实例
    Wparam与Lparam的区别
    WPARAM和LPARAM的含义
    C# 使用SendMessage 函数
    在WinForm中使用Web Services 来实现 软件 自动升级( Auto Update ) (C#)
  • 原文地址:https://www.cnblogs.com/guojieying/p/13553988.html
Copyright © 2011-2022 走看看