(并发编程)进程池线程池--提交任务的2种方式、协程--yield greenlet,gevent模块
2021-07-03 17:05
标签:自动 count producer 传值 函数 限制 adp append submit g1=spawn(play,‘刘清正‘) (并发编程)进程池线程池--提交任务的2种方式、协程--yield greenlet,gevent模块 标签:自动 count producer 传值 函数 限制 adp append submit 原文地址:https://www.cnblogs.com/3sss-ss-s/p/9621591.html
先造个池子,然后放任务
为什么要用“池”:池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务
池子内什么时候装进程:并发的任务属于计算密集型
池子内什么时候装线程:并发的任务属于IO密集型
# 同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的
# 异步调用:提交完一个任务之后,不在原地等待,结果???,而是直接执行下一行代码,会导致任务是并发执行的
p=ProcessPoolExecutor(4)
obj=p.submit(函数名,参1,参2)
obj.add_done_callback(函数名2)
p.shutdown(wait=True)#(等同于p.close()(不允许向池中放新任务) + p.join())关闭进程池的入口,并且在原地等待进程池内所有任务运行完毕
obj.result()
import time,random,os
print(‘%s%s is running‘ %(name,os.getpid()))
time.sleep(random.randint(1,3))
return n**2
# print(os.cpu_count())
p=ProcessPoolExecutor(4)
#提交任务的两种方式:
# 同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的
# 异步调用:提交完一个任务之后,不在原地等待,结果???,而是直接执行下一行代码,会导致任务是并发执行的
for i in range(10):
# 同步提交
# res=p.submit(task,‘进程pid: ‘,i).result()
# print(res)
future=p.submit(task,‘进程pid: ‘,i)
l.append(future)
print(future.result())
print(‘主‘)
二、协程
1、协程是单线程实现并发
注意:协程是程序员意淫出来的东西,操作系统里只有进程和线程的概念(操作系统调度的是线程)
在单线程下(计算密集型任务)切反而降低效率。
2、实现并发的三种手段:
a单线程下的并发;由程序自己控制,相对速度快
b多线程下的并发;由操作系统控制,相对速度较慢
c多进程下的并发;由操作系统控制,相对速度慢
PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的.
def consumer():
‘‘‘任务1:接收数据,处理数据‘‘‘
while True:
x=yield
‘‘‘任务2:生产数据‘‘‘
g=consumer()
next(g)
for i in range(10000000):
g.send(i)
producer() #1.0202116966247559
stop=time.time()
print(stop-start)
import time
def task1():
res=1
for i in range(1000000):
res+=i
yield
time.sleep(10000) #yield不会自动跳过阻塞
print(‘task1‘)
g=task1()
res=1
for i in range(1000000):
res*=i
next(g)
print(‘task2‘)
task2()
stop=time.time()
print(stop-start)
1、用greenlet(封装yield,遇到IO不自动切)
from greenlet import greenlet
import time
print(‘%s eat 1‘ %name)
time.sleep(30)
g2.switch(‘alex‘) #只在第一次切换时传值
print(‘%s eat 2‘ %name)
g2.switch()
def play(name):
print(‘%s play 1‘ %name)
g1.switch()
print(‘%s play 2‘ %name)
g2=greenlet(play)
g1.switch(‘egon‘)
import gevent
print(‘%s eat 1‘ %name)
gevent.sleep(5) #换成time.sleep(5),不会自动切
print(‘%s eat 2‘ %name)
def play(name):
print(‘%s play 1‘ %name)
gevent.sleep(3)
print(‘%s play 2‘ %name)
g2=gevent.spawn(play,‘alex‘)
# g1.join()
# g2.join()
gevent.joinall([g1,g2])
from gevent import monkey;monkey.patch_all()
from threading import current_thread
from gevent import spawn,joinall #pip3 install gevent
import time
print(‘%s play 1‘ %name)
time.sleep(5)
print(‘%s play 2‘ %name)
print(‘%s eat 1‘ %name)
time.sleep(3)
print(‘%s eat 2‘ %name)
g2=spawn(eat,‘刘清正‘)
# g2.join()
joinall([g1,g2])
文章标题:(并发编程)进程池线程池--提交任务的2种方式、协程--yield greenlet,gevent模块
文章链接:http://soscw.com/index.php/essay/101354.html