• python-进程-其他方法(2)


    OK上一篇的内容大家都记住了吗?  嫌多吗!   不要急,今天继续,哈哈,没事,最后几个了

    本篇目录

    1. 管道
    2. 事件
    3. 信号量
    4. 进程池
    5. 进程池的同步方法
    6. 进程池的异步方法
    7. 进程池的回调函数

    一.管道

      进程间通信(IPC)方式二:管道(不推荐使用,了解即可),会导致数据不安全的情况出现,

    由Pipe方法返回的两个连接对象表示管道的两端。每个连接对象都有send和recv方法(除其他之外)。
    注意,如果两个进程(或线程)试图同时从管道的同一端读取或写入数据,那么管道中的数据可能会损坏。
    当然,在使用管道的不同端部的过程中不存在损坏风险。
    话不多说,直接上代码

    from  multiprocessing  import  Process, Pipe    #多导入一个Pipe模块

    def f1(conn):

      from_zhujincheng = conn.recv()                #创建管道接受,

      print('我是子进程')
      print('来自主进程的消息:',from_zhujincheng)


    if __name__ == '__main__':
      conn1,conn2 = Pipe()      #创建一个管道对象,全双工,返回管道的两端,但是一端发送的消息,只能另外一端接收,自己这一端是不能接收的

      #可以将一端或者两端发送给其他的进程,那么多个进程之间就可以通过这一个管道进行通信了
      p1 = Process(target=f1,args=(conn2,))          #这块可以多写一个进程,试一试多进程通信
      p1.start()

      conn1.send('小宝贝,你在哪')      #管道这一端就可以开始发送内容了   也可以用conn1再写一个

      print('我是主进程')

    很简单,这个平时或工作一般用的不多。

    二. 事件  

    python线程的事件用于主进程控制其他进程的执行,事件主要提供了三个方法 set、wait、clear。
    
    事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,
    如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

    上代码

    from   multiprocessing    import    Process,  Event

    e = Event()     #创建事件对象,这个对象的初识状态为False
    print('e的状态是:',e.is_set())

    print('进程运行到这里了')
    e.set()        #将e的状态改为True
    print('e的状态是:',e.is_set())

    e.clear()         #将e的状态改为False

    e.wait()       #e这个事件对象如果值为False,就在我加wait的地方等待

    print('进程过了wait')

      

    基于事件的进程通信

    import  time

    from  multiprocessing    import  Process,Event

    def f1(e):

      time.sleep(2)

      n = 100

      print("子进程计算结果为",n)

      e.set()          #将e的状态改为True

    if __name__=="__main__":

      e = Event()            #创建事件对象

      p = Process(target = f1,args = (e,)

      p.start()

      print("主进程等待。。。")

      e.wait()            #阻塞,是false时,阻塞,等e的状态改为True时,就可以往下执行

      print("还安好")

    知识是活的,别学死了,大家可以试一试,这个还可以怎么用

    三. 信号量

    互斥锁同时只允许一个线程更改数据,而信号量Semaphore是同时允许一定数量的线程更改数据 。
    假设商场里有4个迷你唱吧,所以同时可以进去4个人,如果来了第五个人就要在外面等待,等到有人出来才能再进去玩。
    实现:
    信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞。这是迪科斯彻(Dijkstra)信号量概念P()和V()的Python实现。信号量同步机制适用于访问像服务器这样的有限资源。
    信号量与进程池的概念很像,但是要区分开,信号量涉及到加锁的概念

    上代码
    import time
    import random
    from multiprocessing import Process,Semaphore

    def f1(i,s)
      s.acquire() #这是锁。大家都还知道吧
      print("%s男嘉宾到了"%i)
      time.sleep(random.randint(1,3))
      s.release() #这也是锁,记住了
    if __name__=="__main__":
      s = Semaphore(4)   #计数器,可以一次进4个,通俗来说就是一次锁4个
      for i in range(10):
        p = Process(target = f1,args=(i,s)
        p.start()

    四. 进程池同步方法

    为什么要有进程池?进程池的概念。

      在程序实际处理问题过程中,忙时会有成千上万的任务需要被执行,闲时可能只有零星任务。那么在成千上万个任务需要被执行的时候,我们就需要去创建成千上万个进程么?首先,创建进程需要消耗时间,销毁进程(空间,变量,文件信息等等的内容)也需要消耗时间。第二即便开启了成千上万的进程,操作系统也不能让他们同时执行,维护一个很大的进程列表的同时,调度的时候,还需要进行切换并且记录每个进程的执行节点,也就是记录上下文(各种变量等等乱七八糟的东西,虽然你看不到,但是操作系统都要做),这样反而会影响程序的效率。因此我们不能无限制的根据任务开启或者结束进程。就看我们上面的一些代码例子,你会发现有些程序是不是执行的时候比较慢才出结果,就是这个原因,那么我们要怎么做呢?

      在这里,要给大家介绍一个进程池的概念,定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中的进程来处理任务,等到处理完毕,进程并不关闭,而是将进程再放回进程池中继续等待任务。如果有很多任务需要执行,池中的进程数量不够,任务就要等待之前的进程执行任务完毕归来,拿到空闲进程才能继续执行。也就是说,池中进程的数量是固定的,那么同一时间最多有固定数量的进程在运行。这样不会增加操作系统的调度难度,还节省了开闭进程的时间,也一定程度上能够实现并发效果

    内容有点多,慢慢看吧

    上代码

    import   time

    from  multiprocessing  import  Process,Pool     #pool = Pool(4)这个就是进程池方法   前边变量随便定义不是非得pool

    def   f1(n):

      time.sleep(1)

      return  n*n

    if __name__=="__main__":

      pool = Pool(4)                  #里面这个参数是指定进程池中有多少个进程用的,4表示4个进程,如果不传参数,默认开启的进程数一般是cpu的个数,cpu个数是看你的电脑是几核的

      for  i  in  range(10):

        print("xxxx")

        res = pool.apply(f1,args = (i,))     #同步方法,指的是一个一个的出结果,相当于排队一样

        print(res)

    五. 进程异步方法

    import time
    from multiprocessing import Process,Pool

    def   f1(n):
      time.sleep(0.5)
      # print(n)
      return n*n

    if __name__ == '__main__':

      pool = Pool(4)

      res_list = []
      for i in range(10):
      print('xxxx')
      #异步给进程池提交任务
      res = pool.apply_async(f1,args=(i,))
      res_list.append(res)

      # print('等待所有任务执行完')
      # pool.close() #锁住进程池,意思就是不让其他的程序再往这个进程池里面提交任务了
      # pool.join()

    #打印结果,如果异步提交之后的结果对象
    for i in res_list:
      print(i.get())

      # time.sleep(10)

    六.进程的回调函数

    import  os
    from  multiprocessing   import   Pool,  Process

    def   f1(n):
      print('进程池里面的进程id',os.getpid())
      print('>>>>',n)
      return n*n

    def   f2(asdf):
      print('>>>>>>>>>>>>>',os.getpid())
      print('回调函数中的结果:',asdf)
      # print('回调函数中的结果:',s.get())

    if __name__ == '__main__':
      pool = Pool(4)
      res = pool.apply_async(f1,args=(5,),f2)          #异步就是不排队了一个一个的来了,直接一次性4个4个的来。
      pool.close()
      pool.join()
      # print(res.get())
      print('主进程的进程id',os.getpid())



  • 相关阅读:
    前端使用 node-gyp 构建 Native Addon
    CHANGELOG 的实现
    深入 JavaScript 中的对象以及继承原理
    使用electron进行原生应用的打包(2)---主进程与渲染进程之间的通信
    使用electron进行原生应用的打包
    Babel编译
    HTML布局四剑客-Flex,Grid,Table,Float
    关于vtt 与 srt 字幕 的相互转换
    关于websocket
    关于jQuery中nth-child和nth-of-type的详解
  • 原文地址:https://www.cnblogs.com/python-lyy/p/10267981.html
Copyright © 2020-2023  润新知