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())



猜你喜欢

转载自www.cnblogs.com/python-lyy/p/10267981.html