一、生产者消费者

  主要是为解耦(借助队列来实现生产者消费者模型)

  import queue  # 不能进行多进程之间的数据传输

  (1)from multiprocessing import Queue    借助Queue解决生产者消费者模型,队列是安全的。

    q = Queue(num)

    num :为队列的最大长度

    q.get() # 阻塞等待获取数据,如果有数据直接获取,如果没有数据,阻塞等待

    q.put() # 阻塞,如果可以继续往队列中放数据,就直接放,不能放就阻塞等待

    q.get_nowait() # 不阻塞,如果有数据直接获取,没有数据就报错

    q.put_nowait() # 不阻塞,如果能往队列中放数据直接放,不可以就报错

    

  (2)from multiprocessing import JoinableQueue  # 可连接的队列

    JoinableQueue 是继承Queue  ,所以可以使用Queue中的方法

    并且JoinableQueue 又多了两个方法

    q.join() # 用于生产者。等待q.task_done的返回结果,通过返回结果,生产者就能获得消费者当前消费了多少个数据。

    q.task_done() # 用于消费者,是指每消费队列中的一个数据,就给join返回一个标识。

  1. from multiprocessing import Queue,Process,Pool,JoinableQueue
  2.  
  3. def consumer(q,lis):
  4. while 1:
  5. for i in lis:
  6. print(i + '拿走了' + q.get())
  7. q.task_done() # get() 一次就会给生产者的join返回一次数据
  8.  
  9. def producer(q,name1):
  10. for i in range(1,9):
  11. q.put(name1 + '第%s号剑'% i)
  12. q.join() # 记录了生产者往队列中添加了8个数据,此时会阻塞,等待消费返回8次数据,后生产者进程才会结束
  13.  
  14. if __name__ == '__main__':
  15. q = JoinableQueue() # 实例化一个队列
  16. p = Process(target=consumer,args=(q,['盖聂','卫庄','高渐离','胜七','掩日']))
  17. p1 = Process(target=producer,args=(q,'越王八剑'))
  18. p.daemon = True # 注意是把消费者设置为守护进程,会随着主进程的结束而结束。
  19. p.start()
  20. p1.start()
  21. p1.join() # 主进程会等待生产者进程结束后才结束,而生产者进程又会等待消费者进程消费完以后才结束。

二、进程之间的共享内存

  from multiprocessing import Manager,Value

  m = Manager()

  num = m.dict({键 :值})

  num = m.list([1,2,3])

  1. from multiprocessing import Process,Manager,Value
  2.  
  3. def func(num):
  4. for i in num:
  5. print(i - 1) # 结果为:0,1,2
  6.  
  7. if __name__ == '__main__':
  8. m = Manager() # 用来进程之间共享数据的
  9. num = m.list([1,2,3])
  10. p = Process(target=func,args=(num,))
  11. p.start()
  12. p.join() # 等待func子进程执行完毕后结束
  13.  
  14. #################Value################
  15.  
  16. from multiprocessing import Process,Manager,Value
  17.  
  18. def func1(num):
  19. print(num)
  20. num.value += 1 # 和Manager用法不一样
  21. print(num.value)
  22.  
  23. if __name__ == '__main__':
  24. num = Value('i',123) # Manager里面不需要传参数
  25. p = Process(target=func1,args=(num,))
  26. p.start()
  27. p.join()

三、进程池

  进程池:一个池子,里边有固定数量的进程。这些进程一直处于待命状态,一旦有任务来,马上就去处理。

  进程池还会帮程序员去管理池中的进程。

  from multiprocessing import Pool

  p = Pool(os.cpu_count() + 1)

  进程池有三个方法:

    map(func,iterable)     有返回值

    iterable:可迭代对象,是把可迭代对象中的每个元素一次传给任务函数当参数 

  1. from multiprocessing import Pool
  2.  
  3. def func(num):
  4. num += 1
  5. print(num)
  6. return num # 返回给map方法
  7.  
  8. if __name__ == '__main__':
  9. p = Pool()
  10. res = p.map(func,[i for i in range(10)]) # 参数为目标对象和可迭代对象
  11. p.close()
  12. p.join() # 等待子进程结束
  13. print('主进程',res) # res是一个列表

    apply(func,args=()) :apply的实现是进程之间是同步的,池中的进程一个一个的去执行。

    func :进程池中的进程执行的任务函数。

    args :可迭代对象型的参数,是传给任务函数的参数。

    同步处理任务时,不需要close和join

    同步处理任务时,进程池中的所有进程是普通进程(主进程需要等待其子进程执行结束)

  1. from multiprocessing import Pool
  2.  
  3. def func(num):
  4. num += 1
  5. return num
  6.  
  7. if __name__ == '__main__':
  8. p = Pool(5) # 实例化5个进程
  9. for i in range(100):
  10. res = p.apply(func,args=(i,)) # 这里传的参数是元祖,这里是同步执行
  11. print(res)

    apply_async(func,args=(),callback=None) :进城之间是异步的,

    func :进程池中的进程执行的任务函数。

    args :可迭代对象型的参数,是传给任务函数的参数

  1. from multiprocessing import Pool
  2.  
  3. def func(num):
  4. num += 1
  5. return num
  6.  
  7. if __name__ == '__main__':
  8. p = Pool(5) # 实例化5个进程
  9. lis = []
  10. for i in range(100):
  11. res = p.apply_async(func,args=(i,)) # 异步执行,5个进程同时去调用func
  12. lis.append(res)
  13. print(res) # 打印结果为 <multiprocessing.pool.ApplyResult object at 0x0347F3D0>
  14. p.close() # Pool中用apply_async异步执行时必须关闭进程
  15. p.join() # 因为是异步执行所以需要等待子进程结束
  16. print(lis) # 100个<multiprocessing.pool.ApplyResult object at 0x0347F3D0> 这种存放在列表中
  17. [print(i.get()) for i in lis] # 输出100个数字[1......100]

    callback :回调函数,就是说每当进程池中有进程处理完任务,返回的结果可以交给回调函数,由回调函数进行进一步的处理,回调函数只有异步才有,同步是没有的

    异步处理任务时,进程池中的所有进程是守护进程(主进程代码执行完毕守护进程就结束)

    异步处理任务时,必须要加上close和join

    回调函数的使用:

      进程的任务函数的返回值,被当成回调函数的形参接收到,以此进行进一步的处理操作

      回调函数是由主进程调用的,而不是子进程,子进程只负责把结果传递给回调函数。

  1. from multiprocessing import Pool
  2. import requests
  3. import os
  4.  
  5. def func(ulr):
  6. res = requests.get(ulr)
  7. print('func进程的pid:%s' % os.getpid(),'父进程的pid:%s' % os.getppid())
  8. if res.status_code == 200:
  9. return ulr,res.text
  10.  
  11. def cal_back(sta): # func中返回的值被自动调用,并当成形参传进来
  12. ulr,text = sta
  13. print('callback回调函数的pid:%s'% os.getpid(),'父进程的pid:%s' % os.getppid())
  14. # 回调函数的pid和父进程的pid一样
  15.  
  16. if __name__ == '__main__':
  17. p = Pool(5)
  18. lis = ['https://www.baidu.com',
  19. 'http://www.jd.com',
  20. 'http://www.taobao.com',
  21. 'http://www.mi.com',
  22. 'http://www.cnblogs.com',
  23. 'https://www.bilibili.com',
  24. ]
  25. print('父进程的pid:%s' % os.getpid())
  26. for i in lis:
  27. p.apply_async(func,(i,),callback=cal_back)
  28. # 异步的执行每一个进程,这里的传参和Process不同,这里必须这样写callback=cal_back
  29. # 异步执行程序func,在每个任务结束后,在func中return回一个结果,这个结果会自动的被callback函数调用,并当成形参来接收。
  30. p.close() # 进程间异步必须加上close()
  31. p.join() # 等待子进程的结束

四、管道机制

  from multiprocessing import Pipe

  con1,con2 = Pipe()

  管道是不安全的

  管道是用于多进程之间通信的一种方式。

  如果在单进程中使用管道,con1发数据,那么就用con2来收数据

              con2发数据,那么就用con1来收数据

  如果在多进程中使用管道,那么就必须是父进程使用con1收,子进程就必须使用con2发

                    父进程使用con1发,子进程就必须使用con2收

                    父进程使用con2收,子进程就必须使用con1发

                    父进程使用con2发,子进程就必须使用con1收

  在管道中有一个著名的错误叫做EOFError。是指,父进程如果关闭了发送端,子进程还继续收数据,那么就会引发EOFError。 

  1. # 单进程中管道的应用
  2. from multiprocessing import Pipe
  3.  
  4. con1,con2 = Pipe() # 管道机制
  5.  
  6. con1.send('') # con1发送,需要con2来接收 是固定
  7. print(con2.recv())
  8. con2.send('') # con2发送,需要con1来接收 是固定
  9. print(con1.recv())
  1. # 多进程中管道的应用
  2. from multiprocessing import Process,Pipe
  3.  
  4. def func(con):
  5. con1,con2 = con
  6. con1.close() # 因为子进程只用con2与父进程通信,所以关闭了
  7. while 1:
  8. try:
  9. print(con2.recv()) # 接收父进程con1发来的数据
  10. except EOFError: # 如果父进程的con1发完数据,并关闭管道,子进程的con2继续接收数据,就会报错。
  11. con2.close() # 当接到报错,此时数据已经接收完毕,关闭con2管道。
  12. break # 退出循环
  13.  
  14. if __name__ == '__main__':
  15. con1,con2 = Pipe()
  16. p = Process(target=func,args=(con1,con2))
  17. p.start()
  18. con2.close() # 因为父进程是用con1来发数据的,con2提前关闭。
  19. for i in range(10): # 生产数据
  20. con1.send('郭%s' % i) # 给子进程的con2发送数据
  21. con1.close() # 生产完数据,关闭父进程的con1管道

joinablequeue模块 生产者消费者模型 Manager模块 进程池 管道的更多相关文章

  1. python 之 并发编程(生产者消费者模型、守护进程的应用)

    9.8 生产者消费者模型 该模型中包含两类重要的角色: 1.生产者:将负责造数据的任务比喻为生产者 2.消费者:接收生产者造出的数据来做进一步的处理的被比喻成消费者 实现生产者消费者模型三要素:1.生 ...

  2. [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]

    [并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...

  3. 生产者消费者模型及Golang简单实现

    简介:介绍生产者消费者模型,及go简单实现的demo. 一.生产者消费者模型 生产者消费者模型:某个模块(函数等〉负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.协程 ...

  4. day 7-5 生产者消费者模型

    一. 生产者和消费者模型 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 二. 为什么要使用生产者和消费者模式 ...

  5. 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)

    参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...

  6. 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型

    一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...

  7. 并发、并行、同步、异步、全局解释锁GIL、同步锁Lock、死锁、递归锁、同步对象/条件、信号量、队列、生产者消费者、多进程模块、进程的调用、Process类、

    并发:是指系统具有处理多个任务/动作的能力. 并行:是指系统具有同时处理多个任务/动作的能力. 并行是并发的子集. 同步:当进程执行到一个IO(等待外部数据)的时候. 异步:当进程执行到一个IO不等到 ...

  8. 并发编程 - 进程 - 1.队列的使用/2.生产者消费者模型/3.JoinableQueue

    1.队列的使用: 队列引用的前提: 多个进程对同一块共享数据的修改:要从硬盘读文件,慢,还要考虑上锁: 所以就出现了 队列 和 管道 都在内存中(快): 队列 = 管道 + 上锁 用队列的目的: 进程 ...

  9. python网络编程--进程(方法和通信),锁, 队列,生产者消费者模型

    1.进程 正在进行的一个过程或者说一个任务.负责执行任务的是cpu 进程(Process: 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在 ...

随机推荐

  1. Fix-Dell iDRAC 7 error: RAC0218: The maximum number of user sessions is reached

    Hi Everyone, We came across the following error while performing some preventative maintenance check ...

  2. 成为Java顶尖程序员 ,看这11本书就够了

    以下是我推荐给Java开发者们的一些值得一看的好书.但是这些书里面并没有Java基础.Java教程之类的书,不是我不推荐,而是离我自己学习 Java基础技术也过去好几年了,我学习的时候看的什么也忘了, ...

  3. javascript面向对象之Object.defineProperty(a,b,c)

    /* Object.defineProperty(a,b,c);介绍 a:需要属性设置的对象 b:需要设置的属性名,(键值) c:是一个用于描述属性值得json数据.这个json数据有configur ...

  4. php for 循环使用实例介绍

    for 循环用于您预先知道脚本需要运行的次数的情况. 语法 for (初始值; 条件; 增量) { 要执行的代码; } 参数: 初始值:主要是初始化一个变量值,用于设置一个计数器(但可以是任何在循环的 ...

  5. 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #17 如何使用ext4

    HACK #17 如何使用ext4 本节介绍ext4的编写和挂载方法.开发版ext4的使用方法.ext4是ext3的后续文件系统,从Linux 2.6.19开始使用.现在主要的发布版中多数都是采用ex ...

  6. faker之python构造虚拟数据

    python中可以使用faker来制造一些虚拟数据 首选安装faker pip install Faker 老版的叫法是faker-factory,但是已不适用 使用faker.Factory.cre ...

  7. python函数入门

    知识内容: 1.函数的作用 2.函数的定义与调用 3.函数的返回值 4.函数的参数 5.局部变量与全局变量 6.作用域 一.函数的作用 1.复用代码 将可能重复执行的代码封装成函数,并在需要执行的地方 ...

  8. JQ-用户注册用到的图形验证码,短信验证码点击事件,切换active类

    // 点击切换图形验证码 页面加载完后执行,类似window.onload $(function () { var imgCaptcha = $(".img-captcha"); ...

  9. SpringMVC + Mybatis 多数据源配置

    比较常用的配置,多数据源.主从等等. 大概的逻辑是: 1.spring-mybatis.xml中配置多个数据源 2.使用Spring提供的AbstractRoutingDataSource类来根据请求 ...

  10. Spring Boot实践——Mybatis分页插件PageHelper的使用

    出自:https://blog.csdn.net/csdn_huzeliang/article/details/79350425 在springboot中使用PageHelper插件有两种较为相似的方 ...