一.为何要用到异步
博主在工作中遇到了以下问题,开发接口爬取数据代码完成之后要写入缓存,但是服务器带宽不是很高,在存入数据库的过程花费2-5s(io延迟),这样就大大影响了接口的性能,于是想到了使用异步存储。
二.了解异步编程
- 为完成某个任务,不同程序单元之间过程中无需通信协调,也能完成任务的方式。
- 不相关的程序单元之间可以是异步的。
- 例如,爬虫下载网页。调度程序调用下载程序后,即可调度其他任务,而无需与该下载任务保持通信以协调行为。不同网页的下载、保存等操作都是无关的,也无需相互通知协调。这些异步操作的完成时刻并不确。
三.线程异步
原理:使用线程类threading.Thread调用函数
应用:通过线程调用的方式,来达到异步非阻塞的效果,也就是说主程序无需等待线程执行完毕,仍然可以继续向下执行。
Python多线程详解:https://www.cnblogs.com/tkqasn/p/5700281.html
代码实例:
同步阻塞代码
1 import threading,time 2 3 def thead(num): 4 time.sleep(1) 5 print("阻塞程序%s开始执行"%num) 6 time.sleep(3) 7 print("阻塞程序%s执行完毕"%num) 8 9 def main(): 10 print("主方法开始执行") 11 12 for i in range(1,3): 13 thead(i) 14 15 print("主方法执行完毕") 16 return 17 18 if __name__ == '__main__': 19 print(time.ctime()) 20 num = main() 21 print("返回结果为%s"%num) 22 print(time.ctime())
Wed Nov 21 09:22:56 2018
主方法开始执行
阻塞程序1开始执行
阻塞程序1执行完毕
阻塞程序2开始执行
阻塞程序2执行完毕
主方法执行完毕
返回结果为None
Wed Nov 21 09:23:04 2018
线程异步,无需等待线程执行
import threading,time
def thead(num):
# time.sleep(1)
print("线程%s开始执行"%num)
time.sleep(3)
print("线程%s执行完毕"%num)
def main():
print("主方法开始执行")
#创建2个线程
poll = []#线程池
for i in range(1,3):
thead_one = threading.Thread(target=thead, args=(i,))
poll.append(thead_one) #线程池添加线程
for n in poll:
n.start() #准备就绪,等待cpu执行
print("主方法执行完毕")
return
if __name__ == '__main__':
print(time.ctime())
num = main()
print("返回结果为%s"%num)
print(time.ctime())
Wed Nov 21 09:48:00 2018
主方法开始执行
主方法执行完毕
返回结果为None
Wed Nov 21 09:48:00 2018
线程1开始执行
线程2开始执行
线程1执行完毕
线程2执行完毕
以上代码是在python3.5版本测试运行。实际工作中可能会遇到一些bug,暂时还没发现。
扫描二维码关注公众号,回复:
4169731 查看本文章
接口得到数据和写入缓存分开来做,避免了IO操作延时,接口响应时间缩短,这样我的目的就达到了。
第一次接触异步的概念,在网上了解到了一些异步模块asyncio,python异步编程的概念,还有很多需要学习的地方,所以后续还会继续更新此类博客。