python进程池使用协程池_Python(进程池与协程)

1.进程池与线程池:

为什么要用“池”:池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务

池子内什么时候装进程:并发的任务属于计算密集型

池子内什么时候装线程:并发的任务属于IO密集型1、进程池from concurrent.futures importProcessPoolExecutor,ThreadPoolExecutorimporttime,os,randomdeftask(x):print('%s 接客' %os.getpid())

time.sleep(random.randint(2,5))return x**2

if __name__ == '__main__':

p=ProcessPoolExecutor() #默认开启的进程数是cpu的核数

#alex,武佩奇,杨里,吴晨芋,张三

for i in range(20):

p.submit(task,i)2、线程池from concurrent.futures importProcessPoolExecutor,ThreadPoolExecutorimporttime,os,randomdeftask(x):print('%s 接客' %x)

time.sleep(random.randint(2,5))return x**2

if __name__ == '__main__':

p=ThreadPoolExecutor(4) #默认开启的线程数是cpu的核数*5

#alex,武佩奇,杨里,吴晨芋,张三

for i in range(20):

p.submit(task,i)2.同步、异步、阻塞、非阻塞1、阻塞与非阻塞指的是程序的两种运行状态

阻塞:遇到IO就发生阻塞,程序一旦遇到阻塞操作就会停在原地,并且立刻释放CPU资源

非阻塞(就绪态或运行态):没有遇到IO操作,或者通过某种手段让程序即便是遇到IO操作也不会停在原地,执行其他操作,力求尽可能多的占有CPU2、同步与异步指的是提交任务的两种方式:

同步调用:提交完任务后,就在原地等待,直到任务运行完毕后,拿到任务的返回值,才继续执行下一行代码

异步调用:提交完任务后,不在原地等待,直接执行下一行代码。等全部执行完毕后取出结果from concurrent.futures importProcessPoolExecutor,ThreadPoolExecutorimporttime,os,randomdeftask(x):print('%s 接客' %x)

time.sleep(random.randint(1,3))return x**2

if __name__ == '__main__':#异步调用

p=ThreadPoolExecutor(4) #默认开启的线程数是cpu的核数*5

#alex,武佩奇,杨里,吴晨芋,张三

obj_l=[]for i in range(10):

obj=p.submit(task,i)

obj_l.append(obj)#p.close()

#p.join()

p.shutdown(wait=True) (等同于p.close()(不允许向池中放新任务) +p.join())print(obj_l[3].result())print('主')#同步调用

p=ThreadPoolExecutor(4) #默认开启的线程数是cpu的核数*5

#alex,武佩奇,杨里,吴晨芋,张三

for i in range(10):

res=p.submit(task,i).result()print('主')2.协程1、单线程下实现并发:协程 (为了提高效率;但不是说所有协程都会提升效率)

并发指的多个任务看起来是同时运行的;并发实现的本质:切换+保存状态

有效的协程在一定程度‘骗过’了CPU;通过自己内部协调,一遇到IO就切到自己的其他程序中,使得CPU以为这个程序一直在运行,从而使其更有可能处于就绪态或运行态,以更多的占用CPU。2、实现并发的三种手段:

a)单线程下的并发;由程序自己控制,相对速度快

b)多线程下的并发;由操作系统控制,相对速度较慢

c)多进程下的并发;由操作系统控制,相对速度慢3、基于yield保存状态,实现两个任务直接来回切换,即并发的效果 (但yield不会遇到阻塞自动切程序)

PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的.importtimedefconsumer():'''任务1:接收数据,处理数据'''

whileTrue:

x=yield

defproducer():'''任务2:生产数据'''g=consumer()

next(g)for i in range(10000000):

g.send(i)

start=time.time()

producer()#1.0202116966247559

stop=time.time()print(stop-start)#纯计算的任务并发执行

importtimedeftask1():

res=1

for i in range(1000000):

res+=iyieldtime.sleep(10000) #yield不会自动跳过阻塞

print('task1')deftask2():

g=task1()

res=1

for i in range(1000000):

res*=i

next(g)print('task2')

start=time.time()

task2()

stop=time.time()print(stop-start)

一、单线程下实现遇到IO切换1、用greenlet(封装yield,遇到IO不自动切)from greenlet importgreenletimporttimedefeat(name):print('%s eat 1' %name)

time.sleep(30)

g2.switch('alex') #只在第一次切换时传值

print('%s eat 2' %name)

g2.switch()defplay(name):print('%s play 1' %name)

g1.switch()print('%s play 2' %name)

g1=greenlet(eat)

g2=greenlet(play)

g1.switch('egon')2、用gevent模块(封装greenlet,不处理的话,遇到自己的IO才主动切)importgeventdefeat(name):print('%s eat 1' %name)

gevent.sleep(5) #换成time.sleep(5),不会自动切

print('%s eat 2' %name)defplay(name):print('%s play 1' %name)

gevent.sleep(3)print('%s play 2' %name)

g1=gevent.spawn(eat,'egon')

g2=gevent.spawn(play,'alex')#gevent.sleep(100)#g1.join()#g2.join()

gevent.joinall([g1,g2])3、用gevent模块(封装greenlet,处理的话,遇到其他IO也主动切)from gevent importmonkey;monkey.patch_all()from threading importcurrent_threadimportgeventimporttimedefeat():print('%s eat 1' %current_thread().name)

time.sleep(5)print('%s eat 2' %current_thread().name)defplay():print('%s play 1' %current_thread().name)

time.sleep(3)print('%s play 2' %current_thread().name)

g1=gevent.spawn(eat)

g2=gevent.spawn(play)#gevent.sleep(100)#g1.join()#g2.join()

print(current_thread().name)

gevent.joinall([g1,g2])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值