Python_生产者消费者模型、管道、数据共享、进程池
1、生产者消费者模型
生产者 —— 生产数据的人
消费者 —— 消费数据的人
生产者消费者模型:供销数据不平衡的现象。
import time
import random
from multiprocessing import Process, Queue def consumer(q):
while True:
obj = q.get()
print(f'消费了一个数据{obj}')
time.sleep(random.randint(1, 3)) if __name__ == "__main__":
q = Queue()
Process(target=consumer, args=(q,)).start()
for i in range(10):
time.sleep(random.randint(1, 5))
q.put(f"food{i}")
print(f'生产了一个数据food{i}')
生产者消费者速度不一致
D:\Python36\python.exe E:/Python/草稿纸.py
生产了一个数据food0
消费了一个数据food0
生产了一个数据food1
消费了一个数据food1
生产了一个数据food2
消费了一个数据food2
生产了一个数据food3
消费了一个数据food3
生产了一个数据food4
消费了一个数据food4
生产了一个数据food5
消费了一个数据food5
生产了一个数据food6
生产了一个数据food7
消费了一个数据food6
生产了一个数据food8
生产了一个数据food9
消费了一个数据food7
消费了一个数据food8
消费了一个数据food9
结果(阻塞)
import time
import random
from multiprocessing import Process, Queue def consumer(name, q):
while True:
obj = q.get()
print(f'{name}吃了一个{obj}')
time.sleep(random.randint(1, 3)) def producer(name, food, q):
for i in range(10):
time.sleep(random.randint(1, 5))
q.put(f'{name}生产的{food}{i}')
print(f'{name}生产了一个数据{food}{i}') if __name__ == '__main__':
q = Queue()
Process(target=consumer, args=('alex', q)).start()
Process(target=producer, args=('yuan', '泔水', q)).start()
Process(target=producer, args=('egon', '骨头', q)).start()
供大于求
D:\Python36\python.exe E:/Python/草稿纸.py
egon生产了一个数据骨头0
alex吃了一个egon生产的骨头0
yuan生产了一个数据泔水0
egon生产了一个数据骨头1
alex吃了一个yuan生产的泔水0
alex吃了一个egon生产的骨头1
yuan生产了一个数据泔水1
egon生产了一个数据骨头2
alex吃了一个yuan生产的泔水1
egon生产了一个数据骨头3
yuan生产了一个数据泔水2
alex吃了一个egon生产的骨头2
alex吃了一个egon生产的骨头3
egon生产了一个数据骨头4
alex吃了一个yuan生产的泔水2
yuan生产了一个数据泔水3
alex吃了一个egon生产的骨头4
alex吃了一个yuan生产的泔水3
yuan生产了一个数据泔水4
egon生产了一个数据骨头5
yuan生产了一个数据泔水5
alex吃了一个yuan生产的泔水4
yuan生产了一个数据泔水6
egon生产了一个数据骨头6
alex吃了一个egon生产的骨头5
yuan生产了一个数据泔水7
alex吃了一个yuan生产的泔水5
yuan生产了一个数据泔水8
alex吃了一个yuan生产的泔水6
egon生产了一个数据骨头7
alex吃了一个egon生产的骨头6
yuan生产了一个数据泔水9
alex吃了一个yuan生产的泔水7
egon生产了一个数据骨头8
alex吃了一个yuan生产的泔水8
egon生产了一个数据骨头9
alex吃了一个egon生产的骨头7
alex吃了一个yuan生产的泔水9
alex吃了一个egon生产的骨头8
alex吃了一个egon生产的骨头9
结果(consumer结束不了)
import time
import random
from multiprocessing import Process, Queue def consumer(name, q):
while True:
obj = q.get() # 阻塞
if obj is None:
break
print(f'{name}吃了一个{obj}')
time.sleep(random.randint(1, 3)) def producer(name, food, q):
for i in range(10):
time.sleep(random.randint(1, 5))
q.put(f'{name}生产的{food}{i}')
print(f'{name}生产了一个{food}{i}') if __name__ == '__main__':
q = Queue()
Process(target=consumer, args=('alex', q)).start()
Process(target=consumer, args=('wusir', q)).start()
p1 = Process(target=producer, args=('yuan', '泔水', q))
p1.start()
p2 = Process(target=producer, args=('egon', '骨头', q))
p2.start()
p1.join()
p2.join()
q.put(None)
q.put(None)
数据被消费完就结束进程
D:\Python36\python.exe E:/Python/草稿纸.py
egon生产了一个骨头0
alex吃了一个egon生产的骨头0
yuan生产了一个泔水0
wusir吃了一个yuan生产的泔水0
yuan生产了一个泔水1
alex吃了一个yuan生产的泔水1
egon生产了一个骨头1
yuan生产了一个泔水2
alex吃了一个egon生产的骨头1
wusir吃了一个yuan生产的泔水2
egon生产了一个骨头2
alex吃了一个egon生产的骨头2
yuan生产了一个泔水3
wusir吃了一个yuan生产的泔水3
egon生产了一个骨头3
wusir吃了一个egon生产的骨头3
yuan生产了一个泔水4
wusir吃了一个yuan生产的泔水4
egon生产了一个骨头4
alex吃了一个egon生产的骨头4
yuan生产了一个泔水5
wusir吃了一个yuan生产的泔水5
egon生产了一个骨头5
alex吃了一个egon生产的骨头5
egon生产了一个骨头6
wusir吃了一个egon生产的骨头6
yuan生产了一个泔水6
alex吃了一个yuan生产的泔水6
yuan生产了一个泔水7
alex吃了一个yuan生产的泔水7
egon生产了一个骨头7
wusir吃了一个egon生产的骨头7
yuan生产了一个泔水8
alex吃了一个yuan生产的泔水8
yuan生产了一个泔水9
wusir吃了一个yuan生产的泔水9
egon生产了一个骨头8
alex吃了一个egon生产的骨头8
egon生产了一个骨头9
wusir吃了一个egon生产的骨头9 Process finished with exit code 0
结果
q.join() 对这个队列进行阻塞,这个队列中的所有值被取走,且执行了task_done.
import time
from multiprocessing import Process, JoinableQueue def consumer(q):
while True:
print(q.get())
time.sleep(0.3)
q.task_done() # 通知队列一个数据已经被处理完了 if __name__ == "__main__":
q = JoinableQueue()
c = Process(target=consumer, args=(q,))
c.daemon = True
c.start()
for i in range(10):
q.put(i) # 10个数据
q.join() # join表示所有的数据都被取走且被处理完才结束阻塞
print('所有数据都被处理完了')
JoinableQueue
D:\Python36\python.exe E:/Python/草稿纸.py
0
1
2
3
4
5
6
7
8
9
所有数据都被处理完了 Process finished with exit code 0
结果
import time
import random
from multiprocessing import Process, JoinableQueue def consumer(name, q):
while True:
obj = q.get() # 阻塞
print(f'{name}吃了一个{obj}')
time.sleep(random.randint(1, 3))
q.task_done() def producer(name, food, q):
for i in range(10):
time.sleep(random.randint(1, 5))
q.put(f'{name}生产的{food}{i}')
print(f'{name}生产了一个{food}{i}') if __name__ == "__main__":
q = JoinableQueue()
c1 = Process(target=consumer, args=('alex', q))
c2 = Process(target=consumer, args=('wusir', q))
c1.daemon = True
c2.daemon = True
p1 = Process(target=producer, args=('yuan', '泔水', q))
p2 = Process(target=producer, args=('egon', '骨头', q))
c1.start()
c2.start()
p1.start()
p2.start()
p1.join()
p2.join()
q.join()
协调生产者与消费者之间的供给关系
D:\Python36\python.exe E:/Python/草稿纸.py
egon生产了一个骨头0
alex吃了一个egon生产的骨头0
yuan生产了一个泔水0
wusir吃了一个yuan生产的泔水0
egon生产了一个骨头1
wusir吃了一个egon生产的骨头1
egon生产了一个骨头2
alex吃了一个egon生产的骨头2
yuan生产了一个泔水1
wusir吃了一个yuan生产的泔水1
egon生产了一个骨头3
alex吃了一个egon生产的骨头3
yuan生产了一个泔水2
wusir吃了一个yuan生产的泔水2
egon生产了一个骨头4
alex吃了一个egon生产的骨头4
yuan生产了一个泔水3
wusir吃了一个yuan生产的泔水3
egon生产了一个骨头5
alex吃了一个egon生产的骨头5
yuan生产了一个泔水4
wusir吃了一个yuan生产的泔水4
yuan生产了一个泔水5
egon生产了一个骨头6
alex吃了一个yuan生产的泔水5
wusir吃了一个egon生产的骨头6
egon生产了一个骨头7
alex吃了一个egon生产的骨头7
yuan生产了一个泔水6
wusir吃了一个yuan生产的泔水6
yuan生产了一个泔水7
alex吃了一个yuan生产的泔水7
egon生产了一个骨头8
wusir吃了一个egon生产的骨头8
yuan生产了一个泔水8
alex吃了一个yuan生产的泔水8
egon生产了一个骨头9
wusir吃了一个egon生产的骨头9
yuan生产了一个泔水9
alex吃了一个yuan生产的泔水9 Process finished with exit code 0
结果
队列:
维护了一个先进先出的顺序.
且保证了数据在进程之间的安全.
2、管道
管道在数据管理上是不安全的
队列的实现机制就是 管道 + 锁
from multiprocessing import Pipe, Process # 左发右
lp, rp = Pipe()
lp.send([1, 2, 3])
print(rp.recv())
# 右发左
rp.send('aa')
print(lp.recv())
管道通信
D:\Python36\python.exe E:/Python/草稿纸.py
[1, 2, 3]
aa Process finished with exit code 0
结果
from multiprocessing import Pipe, Process def consumer(lp, rp):
lp.close()
while True:
try:
print(rp.recv())
except EOFError:
break if __name__ == '__main__':
lp, rp = Pipe()
Process(target=consumer, args=(lp, rp)).start()
Process(target=consumer, args=(lp, rp)).start()
Process(target=consumer, args=(lp, rp)).start()
Process(target=consumer, args=(lp, rp)).start()
Process(target=consumer, args=(lp, rp)).start()
rp.close()
for i in range(500):
lp.send(f'food{i}')
lp.close()
示例
D:\Python36\python.exe E:/Python/草稿纸.py
food0
food1
food2
food3
food4
food5
food6
food7
food8
food9
food10
food11
food12
food13
food14
food15
food16
food17
food18
food19
food20
food21
food22
food23
food24
food25
food26
food27
food28
food29
food30
food31
food32
food33
food34
food35
food36
food37
food38
food39
food40
food41
food42
food43
food44
food45
food46
food47
food48
food49
food50
food51
food52
food53
food54
food55
food56
food57
food58
food59
food60
food61
food62
food63
food64
food65
food66
food67
food68
food69
food70
food71
food72
food73
food74
food75
food76
food77
food78
food79
food80
food81
food82
food83
food84
food85
food86
food87
food88
food89
food90
food91
food92
food93
food94
food95
food96
food97
food98
food99
food100
food101
food102
food103
food104
food105
food106
food107
food108
food109
food110
food111
food112
food113
food114
food115
food116
food117
food118
food119
food120
food121
food122
food123
food124
food125
food126
food127
food128
food129
food130
food131
food132
food133
food134
food135
food136
food137
food138
food139
food140
food141
food142
food143
food144
food145
food146
food147
food148
food149
food150
food151
food152
food153
food154
food155
food156
food157
food158
food159
food160
food161
food162
food163
food164
food165
food166
food167
food168
food169
food170
food171
food172
food173
food174
food175
food176
food177
food178
food179
food180
food181
food182
food183
food184
food185
food186
food187
food188
food189
food190
food191
food192
food193
food194
food195
food196
food197
food198
food199
food200
food201
food202
food203
food204
food205
food206
food207
food208
food209
food210
food211
food212
food213
food214
food215
food216
food217
food218
food219
food220
food221
food222
food223
food224
food225
food226
food227
food228
food229
food230
food231
food232
food233
food234
food235
food236
food237
food238
food239
food240
food241
food242
food243
food244
food245
food246
food247
food248
food249
food250
food251
food252
food253
food254
food255
food256
food257
food258
food259
food260
food261
food262
food263
food264
food265
food266
food267
food268
food269
food270
food271
food272
food273
food274
food275
food276
food277
food278
food279
food280
food281
food282
food283
food284
food285
food286
food287
food288
food289
food290
food291
food292
food293
food294
food295
food296
food297
food298
food299
food300
food301
food302
food303
food304
food305
food306
food307
food308
food309
food310
food311
food312
food313
food314
food315
food316
food317
food318
food319
food320
food321
food322
food323
food324
food325
food326
food327
food328
food329
food330
food331
food332
food333
food334
food335
food336
food337
food338
food339
food340
food341
food342
food343
food344
food345
food346
food347
food348
food349
food350
food351
food352
food353
food354
food355
food356
food357
food358
food359
food360
food361
food362
food363
food364
food365
food366
food367
food368
food369
food370
food371
food372
food373
food374
food375
food376
food377
food378
food379
food380
food381
food382
food383
food384
food385
food386
food387
food388
food389
food390
food391
food392
food393
food394
food395
food396
food397
food398
food399
food400
food401
food402
food403
food404
food405
food406
food407
food408
food409
food410
food411
food412
food413
food414
food415
food416
food417
food418
food419
food420
food421
food422
food423
food424
food425
food426
food427
food428
food429
food430
food431
food432
food433
food434
food435
food436
food437
food438
food439
food440
food441
food442
food443
food444
food445
food446
food447
food448
food449
food450
food451
food452
food453
food454
food455
food456
food457
food458
food459
food460
food461
food462
food463
food464
food465
food466
food467
food468
food469
food470
food471
food472
food474
food475
food473
food476
food477
food478
food479
food481
food482
food483
food484
food485
food486
food487
food488
food489
food490
food491
food492
food493
food494
food495
food496
food497
food498
food499
food480 Process finished with exit code 0
结果
3、数据共享
普通模式:
from multiprocessing import Manager, Process, Lock def work(d, lock):
with lock: # 不加锁而操作共享的数据,肯定会出现数据错乱
d['count'] -= 1 if __name__ == '__main__':
lock = Lock()
m = Manager()
dic = m.dict({'count': 100})
p_l = []
for i in range(100):
p = Process(target=work, args=(dic, lock))
p_l.append(p)
p.start()
for p in p_l:
p.join()
print(dic)
示例
D:\Python36\python.exe E:/Python/草稿纸.py
{'count': 0} Process finished with exit code 0
结果
上下文管理模式:
from multiprocessing import Manager, Process, Lock def work(d, lock):
with lock: # 不加锁而操作共享的数据,肯定会出现数据错乱
d['count'] -= 1 if __name__ == '__main__':
lock = Lock()
with Manager() as m:
dic = m.dict({'count': 100})
p_l = []
for i in range(100):
p = Process(target=work, args=(dic, lock))
p_l.append(p)
p.start()
for p in p_l:
p.join()
print(dic)
示例
D:\Python36\python.exe E:/Python/草稿纸.py
{'count': 0} Process finished with exit code 0
结果
4、进程池
多进程和进程池的对比:
对于纯计算型的代码,使用进程池更好 ——真理
对于高IO的代码,直接使用多进程更好 —— 相对论
结论:进程池比起多进程来说,节省了开启进程回收进程的时间,给操作系统调度进程降低了难度
使用进程池提交任务:
apply # 同步提交任务,没有多进程的优势
apply_async # 异步提交任务,常用,可以通过get方法获取返回值
close # 关闭进程池,阻止往池中添加新的任务
join # join依赖close,一个进程必须先close再join
map # 接收一个任务函数,和一个iterable。节省了for循环和close、join,是一种简便的写法。
apply_async和map相比,操作复杂,但是可以通过get方法获取返回值。
import os
def wahaha(num):
print('子',os.getpid())
return num ** num def call(argv): # 回调函数用的是主进程的资源
print(os.getpid())
print(argv) if __name__ == '__main__':
print('主', os.getpid())
p = Pool(5)
p.apply_async(func=wahaha, args=(50,), callback=call)
p.close()
p.join()
进程池
D:\Python36\python.exe E:/Python/草稿纸.py
主 13636
子 13636
13636
8881784197001252323389053344726562500000000000000000000000000000000000000000000000000 Process finished with exit code 0
结果
Python_生产者消费者模型、管道、数据共享、进程池的更多相关文章
- joinablequeue模块 生产者消费者模型 Manager模块 进程池 管道
一.生产者消费者 主要是为解耦(借助队列来实现生产者消费者模型) import queue # 不能进行多进程之间的数据传输 (1)from multiprocessing import Queue ...
- python 之 并发编程(生产者消费者模型、守护进程的应用)
9.8 生产者消费者模型 该模型中包含两类重要的角色: 1.生产者:将负责造数据的任务比喻为生产者 2.消费者:接收生产者造出的数据来做进一步的处理的被比喻成消费者 实现生产者消费者模型三要素:1.生 ...
- python摸爬滚打之day032 管道 数据共享 进程池
1.进程池 当有成千上万个任务需要被执行的时候,有了进程池我们就不必去创建大量的进程. 首先,创建进程需要消耗时间,销毁进程(空间,变量,文件信息等等的内容)也需要消耗时间, 第二即便开启了成千上万的 ...
- [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]
[并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...
- 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)
参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...
- python 进程锁 生产者消费者模型 队列 (进程其他方法,守护进程,数据共享,进程隔离验证)
#######################总结######### 主要理解 锁 生产者消费者模型 解耦用的 队列 共享资源的时候 是不安全的 所以用到后面的锁 守护进程:p.daem ...
- 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型
本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...
- python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型
一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...
- python 全栈开发,Day39(进程同步控制(锁,信号量,事件),进程间通信(队列,生产者消费者模型))
昨日内容回顾 python中启动子进程并发编程并发 :多段程序看起来是同时运行的ftp 网盘不支持并发socketserver 多进程 并发异步 两个进程 分别做不同的事情 创建新进程join :阻塞 ...
随机推荐
- Syntax error, parameterized types are only available if source level is 1.5 解决方案
在网上找了一个K-means算法的程序,打开,运行,出现了Syntax error,parameterized types are only available if source level is ...
- LeetCode算法题-Number of Segments in a String(Java实现)
这是悦乐书的第226次更新,第239篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第93题(顺位题号是434).计算字符串中的段数,其中段定义为非空格字符的连续序列.请注 ...
- 【Linux常见问题】SecureCRT 终端连接密钥交换失败错误
SecureCRT 终端软件连接linux操作系统,出现如下错误: 英文描述:Key exchange failed. No compatible key exchange method. The s ...
- node基础—global对象(全局对象)
global对象的__filename属性和__dirname属性 __filename属性:返回当前执行的文件的文件路径,该路径是经过解析后的绝对路径,在模块中,该路径是模块文件的路径,此属性并非全 ...
- cf 20190307 Codeforces Round #543 (Div. 2, based on Technocup 2019 Final Round)
B. Mike and Children time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- VS2015应用NuGet
一.什么是Nuget Nuget是 ASP .NET Gallery 的一员.NuGet 是免费.开源的包管理开发工具,专注于在 .NET 应用开发过程中,简单地合并第三方的组件库. 当需要分享开发的 ...
- YYModel HandyJson
数学基础: 以类型集合空间为基础,多阶向量结构间的同构映射: 若两个数学结构之间存在同构映射,那么这两个结构叫做是同构的. 基于集合空间的映射: 原理: 1.根据类型名称获得类型的元信息: 2.根据映 ...
- docker: read tcp 192.168.7.235:36512->54.230.212.9:443: read: connection reset by peer.
在学习rancher的时候去下载rancher/agent镜像的时候,出现报错:docker: read tcp 192.168.7.235:36512->54.230.212.9:443: r ...
- ASP.Net Web API 输出缓存 转载 -- Output caching in ASP.NET Web API
一.Nuget安装相关dll Web API 2 : Install-Package Strathweb.CacheOutput.WebApi2 Web API 1 : Install-Package ...
- P2256 一中校运会之百米跑(map+并查集)
思路:首先处理名字,让字符串直接映射唯一一个数字,这就用map<string, int>即可. 然后,直接用并查集 #include<iostream> #include< ...