Python(进程池与协程)
1.进程池与线程池:
为什么要用“池”:池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务
池子内什么时候装进程:并发的任务属于计算密集型
池子内什么时候装线程:并发的任务属于IO密集型 1、进程池
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time,os,random def task(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 import ProcessPoolExecutor,ThreadPoolExecutor
import time,os,random def task(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操作也不会停在原地,执行其他操作,力求尽可能多的占有CPU 2、同步与异步指的是提交任务的两种方式:
同步调用:提交完任务后,就在原地等待,直到任务运行完毕后,拿到任务的返回值,才继续执行下一行代码
异步调用:提交完任务后,不在原地等待,直接执行下一行代码。等全部执行完毕后取出结果 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time,os,random def task(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:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的. import time
def consumer():
'''任务1:接收数据,处理数据'''
while True:
x=yield def producer():
'''任务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) # 纯计算的任务并发执行
import time
def task1():
res=1
for i in range(1000000):
res+=i
yield
time.sleep(10000) #yield不会自动跳过阻塞
print('task1') def task2():
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 import greenlet
import time def eat(name):
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) g1=greenlet(eat)
g2=greenlet(play)
g1.switch('egon') 2、用gevent模块(封装greenlet,不处理的话,遇到自己的IO才主动切)
import gevent def eat(name):
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) 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 import monkey;monkey.patch_all()
from threading import current_thread
import gevent
import time def eat():
print('%s eat 1' %current_thread().name)
time.sleep(5)
print('%s eat 2' %current_thread().name)
def play():
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])
Python(进程池与协程)的更多相关文章
- Python 线程池,进程池,协程,和其他
本节内容 线程池 进程池 协程 try异常处理 IO多路复用 线程的继承调用 1.线程池 线程池帮助你来管理线程,不再需要每个任务都创建一个线程进行处理任务. 任务需要执行时,会从线程池申请线程,有则 ...
- Python、进程间通信、进程池、协程
进程间通信 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 进程队列queue 不同于线程queue,进程 ...
- Python开发基础-Day32 进程间通信、进程池、协程
进程间通信 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 进程队列queue 不同于线程queue,进程 ...
- python基础之进程间通信、进程池、协程
进程间通信 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 进程队列queue 不同于线程queue,进程 ...
- python进程.线程和协程的总结
I.进程: II.多线程threading总结 threading用于提供线程相关的操作,线程是应用系统中工作的最小单位(cpu调用的最小单位). Python当前版本的多线程没有实现优先级,线程组, ...
- 线程queue、线程进程池,协程
线程queue import queue q = queue.Queue() #先进先出 q = queue.LifoQueue() #先进后出 t = queue.PriorityQueue() # ...
- python3下multiprocessing、threading和gevent性能对比----暨进程池、线程池和协程池性能对比
python3下multiprocessing.threading和gevent性能对比----暨进程池.线程池和协程池性能对比 标签: python3 / 线程池 / multiprocessi ...
- python day 20: 线程池与协程,多进程TCP服务器
目录 python day 20: 线程池与协程 2. 线程 3. 进程 4. 协程:gevent模块,又叫微线程 5. 扩展 6. 自定义线程池 7. 实现多进程TCP服务器 8. 实现多线程TCP ...
- 并发编程(六)——进程/线程池、协程、gevent第三方库
进程/线程池.协程.gevent第三方库 一.进程/线程池 1.进程池 (1)什么是进程池 如果需要创建的子进程数量不大,可以直接利用multiprocess中的Process来创建.但是当需要创建上 ...
随机推荐
- phoenix查询缓慢问题
现象:phoenix刚建表时查找很快,随着数据导入越来越多,查询越来越缓慢,执行explain这个表的计划都需要好几秒,但在hbase shell里查询很快 问题定位:这个是由于system.stat ...
- hash slot(虚拟桶)
在分布式集群中,如何保证相同请求落到相同的机器上,并且后面的集群机器可以尽可能的均分请求,并且当扩容或down机的情况下能对原有集群影响最小. round robin算法:是把数据mod后直接映射到真 ...
- poj 1475 Pushing Boxes 推箱子(双bfs)
题目链接:http://poj.org/problem?id=1475 一组测试数据: 7 3 ### .T. .S. #B# ... ... ... 结果: //解题思路:先判断盒子的四周是不是有空 ...
- nyoj 460 项链 (区间dp)
项链 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子, ...
- C/C++开发平时用的自定义debug函数
一.无颜色版 一.自定义printf #include <stdio.h> #ifdef MYDEBUG #define DEBUG(arg...) {\ printf("[de ...
- liunx下安装eclipse
1.eclipse-jee-mars-1-linux-gtk-x86_64 下载地址:http://download.csdn.net/download/yichen01010/10018917 2. ...
- [Win10应用开发] 使用 Windows 推送服务
前言 Windows 推送服务(WNS)也是 Win10 通知机制中的一种,今天与大家一起学习一下有关WNS的相关知识.使用 Windows 推送服务的前提是你需要有一个微软开发者账号,这样才能得到一 ...
- UML类图简单说明,学习编程思路的必会技能
摘抄记录学习用 先看一张图,图片资源来自于大话设计模式,接下来我要跟着这本书一起走,如侵权,立即删除. 看见上图估计没学过或者不是本专业的没接触过的人,看这一堆估计就不想看了,但别怕一个一个分析. 一 ...
- C++ 类的继承五(类继承中的static关键字)
//类继承中的static关键字 #include<iostream> using namespace std; /* 派生类中的静态成员 基类定义的静态成员,将被所有派生类共享 根据静态 ...
- .htaccess伪静态实例分享
首先配置服务器启动重写模块打开 Apache 的配置文件 httpd.conf .将#LoadModule rewrite_module modules/mod_rewrite前面的#去掉.保存后重启 ...