多进程多线程应用测试教程:
锚定在一定的实际问题上的代码,不是凭空炫技,每种都需要设想使用场景和使用意义
01、最基本的两个多进程的消费者 生产者模式代码示例
--日常代码中常常会出现:
--一边生产,一边处理的场景。有的时候就是简单的两个进程,而不需要涉及到更多的进程安排,这种需求可以按照如下来做
--当然优化的方向也有很多,根据不同的处理逻辑可以嵌套更多的进程和线程达到提高速度的目的
--这里需要注意的是:
--使用multiprocessing自带的Queue作为队列才能在进程间共享变量
--在进程池中使用自带的Queue是不行的
--这里生产的结束信号为:end
--这里消费者会出现等待的情形,如果生产者没有生产出来,会导致阻塞一定要注意
--这里生产了40个。每个耗时0.2s。这种方式只能节约生产和消费梯次执行的时间,将其变为并行
--代码示例如下:
import time
from multiprocessing import Process,Queue
"""
1、生产者 消费者之间使用
"""
# 生产者
def producer(q, name, food):
pro_start = time.time()
# 爬虫爬取数据,执行一个任务
for i in range(3):
time.sleep(0.5)
res = "%s%s" % (food, i)
q.put(res)
print("%s 生产了 %s" % (name, res))
q.put("end")
print("生产者一共耗时:%s"%(str(time.time() - pro_start)))
# 消费者
def consumer(q, name):
con_start = time.time()
while True:
res = q.get()
# time.sleep(0.5)
if res != "end":
print("%s 吃%s" % (name, res))
elif res == "end":
break
print("消费者一共耗时:%s" % (str(time.time() - con_start)))
if __name__ == '__main__':
all_start = time.time()
q = Queue()
# 生产者们:即厨师们
p1 = Process(target=producer, args=(q, 'egon', '包子'))
# 消费者们:即吃货们
c1 = Process(target=consumer, args=(q, 'mike'))
# 开始并等待程序执行完毕
p1.start()
c1.start()
p1.join()
c1.join()
print('主进程结束,耗时:%s'%(str(time.time() - all_start)))
####################### 输出结果 #########################
egon 生产了 包子0
mike 吃包子0
egon 生产了 包子1
mike 吃包子1
egon 生产了 包子2
*** ***
*** ***
egon 生产了 包子39
mike 吃包子39
生产者一共耗时:8.016192197799683
消费者一共耗时:8.016192197799683
主进程结束,耗时:8.164325714111328
02、使用进程池实现的【主要是Manager中Queue的使用】:生产者 消费者模式
--这个相比于代码1,增加了生产者的生产速度。使用了多线程的方式增加了生产速度,消费速度代码上没有变化
。实际是变化了的,因为生产加快以后消费无需等待就是说队列不会被阻塞了,因而也是加快了的
--这里实际是生产了40个,每个生产时间为0.2s,这种不仅将生产和消费并行了起来,而且在进程中套用了线程,并通过Manager的方式将数据传递到另一个进程中。速度大大提高
--代码示例如下:
import time
from multiprocessing import Process,Queue,Manager
from concurrent.futures import ThreadPoolExecutor, as_completed, ProcessPoolExecutor
"""
1、生产者加快生产,消费者不变
"""
# 单个生产者
def sin_producer(sin_pro_list):
q = sin_pro_list[0]
i = sin_pro_list[1]
name = sin_pro_list[2]
food = sin_pro_list[3]
time.sleep(0.2)
res = "%s%s" % (food, i)
q.put(res)
print("%s 生产了 %s" % (name, res))
return None
# 多线程生产者
def producer(q, name, food):
pro_start = time.time()
# 构造参数列表
pro_list = []
for i in range(40):
sin_pro_list = []
sin_pro_list.append(q)
sin_pro_list.append(i)
sin_pro_list.append(name)
sin_pro_list.append(food)
pro_list.append(sin_pro_list)
# 启动多线程
with ThreadPoolExecutor(5) as executor:
all_tasks_01 = [executor.submit(sin_producer, (sin_pro_list)) for sin_pro_list in pro_list]
for future in as_completed(all_tasks_01):
data = future.result()
q.put("end")
print("生产者一共耗时:%s"%(str(time.time() - pro_start)))
# 消费者
def consumer(q, name):
con_start = time.time()
while True:
res = q.get()
if res != "end":
print("%s 吃%s" % (name, res))
elif res == "end":
break
print("消费者一共耗时:%s" % (str(time.time() - con_start)))
if __name__ == '__main__':
all_start = time.time()
# 记住这里使用到了进程池,所以需要使用
q = Manager().Queue()
# 生产者们:即厨师们
p1 = Process(target=producer, args=(q, 'egon', '包子'))
# 消费者们:即吃货们
c1 = Process(target=consumer, args=(q, 'mike'))
# 开始并等待程序执行完毕
p1.start()
c1.start()
p1.join()
c1.join()
print('主进程结束,耗时:%s'%(str(time.time() - all_start)))
###################### 输出结果如下 #########################
egon 生产了 包子3
mike 吃包子3
egon 生产了 包子4
mike 吃包子4
egon 生产了 包子1
*** ***
*** ***
mike 吃包子38
egon 生产了 包子37
mike 吃包子39
生产者一共耗时:1.6091229915618896
消费者一共耗时:1.607128381729126
主进程结束,耗时:1.893364667892456
03、多线程连接数据库查询工作