异步回调 回调: 其实说的是回调函数 ,给异步任务绑定一个函数,当任务完成时会自动调用该函数 具体使用 当你往pool中添加 了一个异步任务,会返回一个表示结果的函数对象,有一个对象的绑定方法add_done_callback,需要一个函数作为参数,注意:回调函数必须有且 只有 一个参数 就是对象本身 通过对象.result()来获取结果 回调函数交给子线程来执行 谁有空谁处理
优点:不用原地等待,任务结果可以立即获取到 表达式:
from concurrent.futures import ThreadPoolExecutor
import requests
import threading
#生产
def get_data(url):
print('%s正在处理%s'%(threading.current_thread().name,url)
resp = requests.get(url)
print("%s获取完成”%url)
return resp.text,url
#消费
def parser_data(f):
res = f.result()
print("解析长度为%s ,地址:%s"%(len(res[0],),res[1]))
print("当前线程:%s"%threading.current_thread().name)
urls = ["https://www.baidu.com/","https://www.bilibili.com/","https://sina.com/"]
pool = ThreadPoolExecutor()
for url in urls:
f= pool.submit(get_data,url)#提交任务
f.add_done_callback(parser_data)#绑定任务
协程就是要用单线程实现并发
为什么需要协程: GIL导致多个线程不能并行,效率低 CPYTHON中多个线程不能并行 一个线程如何能并发: 多道技术
切换+保存状态
首先任务就是一堆代码 一堆代码就可以组成一个函数
如何能使得可以在多个函数之间切换
协程指的就是一个线程完成并发执行
在CPYTHON中 如果你的任务是计算密集型,使用协程无法提高效率,反而在切换任务中导致效率降低,只能靠进程来解决问题
IO密集型 多线程会比多进程效率高,应为线程的开销比进程小得多,本质上协程还是一个线程 所以一旦遇到IO操作 整个线程就卡主了
协程仅在以下场景能够提高效率
1 任务是Io密集型
2 一定要可以检测到Io操作 并且在io即将阻塞时 切换到计算任务,从而使得cpu尽可能多的执行你的线程
greenlet 无法检测io操作
gevent 即可单线程实现并发 又可以检测io操作
import gevent
import gevent.monkey#打补丁必须放在 导入模块之前
gevent.monkey.patch_all()
import time
import threading
def task1():
print (a,b)
print(task1)
print(threading.current_thread())
time.sleep(1)
def task2():
#for i in range(1000):
print("task2")
print(threading.current_thread())
g1 = gevent.spawn(task1,123,321)
g2 = gevent.spawn(task2)
g1.join()
g2.join()