https://www.cnblogs.com/wongbingming/p/9124142.html

在实战中,将会用到以下知识点:

  • 多线程的基本使用
  • Queue消息队列的使用
  • Redis的基本使用
  • asyncio的使用

. 动态添加协程#

在实战之前,我们要先了解下在asyncio中如何将协程态添加到事件循环中的。这是前提。

如何实现呢,有两种方法:

  • 主线程是同步
import time
import asyncio
from queue import Queue
from threading import Thread def start_loop(loop):
# 一个在后台永远运行的事件循环
asyncio.set_event_loop(loop)
loop.run_forever() def do_sleep(x, queue, msg=""):
time.sleep(x)
queue.put(msg) queue = Queue() new_loop = asyncio.new_event_loop() # 定义一个线程,并传入一个事件循环对象
t = Thread(target=start_loop, args=(new_loop,))
t.start() print(time.ctime()) # 动态添加两个协程
# 这种方法,在主线程是同步的
new_loop.call_soon_threadsafe(do_sleep, 6, queue, "第一个")
new_loop.call_soon_threadsafe(do_sleep, 3, queue, "第二个") while True:
msg = queue.get()
print("{} 协程运行完..".format(msg))
print(time.ctime())

由于是同步的,所以总共耗时6+3=9秒.

输出结果

Thu May 31 22:11:16 2018
第一个 协程运行完..
Thu May 31 22:11:22 2018
第二个 协程运行完..
Thu May 31 22:11:25 2018
  • 主线程是异步的,这是重点,一定要掌握。。
import time
import asyncio
from queue import Queue
from threading import Thread def start_loop(loop):
# 一个在后台永远运行的事件循环
asyncio.set_event_loop(loop)
loop.run_forever() async def do_sleep(x, queue, msg=""):
await asyncio.sleep(x)
queue.put(msg) queue = Queue() new_loop = asyncio.new_event_loop() # 定义一个线程,并传入一个事件循环对象
t = Thread(target=start_loop, args=(new_loop,))
t.start() print(time.ctime()) # 动态添加两个协程
# 这种方法,在主线程是异步的
asyncio.run_coroutine_threadsafe(do_sleep(6, queue, "第一个"), new_loop)
asyncio.run_coroutine_threadsafe(do_sleep(3, queue, "第二个"), new_loop) while True:
msg = queue.get()
print("{} 协程运行完..".format(msg))
print(time.ctime())

输出结果

由于是同步的,所以总共耗时max(6, 3)=6

Thu May 31 22:23:35 2018
第二个 协程运行完..
Thu May 31 22:23:38 2018
第一个 协程运行完..
Thu May 31 22:23:41 2018

实战:利用redis实现动态添加任务#

对于并发任务,通常是用生成消费模型,对队列的处理可以使用类似master-worker的方式,master主要用户获取队列的msg,worker用户处理消息。

为了简单起见,并且协程更适合单线程的方式,我们的主线程用来监听队列,子线程用于处理队列。这里使用redis的队列。主线程中有一个是无限循环,用户消费队列。

先安装Redis
到 https://github.com/MicrosoftArchive/redis/releases 下载

解压到你的路径。

然后,在当前路径运行cmd,运行redis的服务端。

服务开启后,我们就可以运行我们的客户端了。
并依次输入key=queue,value=5,3,1的消息。

一切准备就绪之后,我们就可以运行我们的代码了。

import time
import redis
import asyncio
from queue import Queue
from threading import Thread def start_loop(loop):
# 一个在后台永远运行的事件循环
asyncio.set_event_loop(loop)
loop.run_forever() async def do_sleep(x, queue):
await asyncio.sleep(x)
queue.put("ok") def get_redis():
connection_pool = redis.ConnectionPool(host='127.0.0.1', db=0)
return redis.Redis(connection_pool=connection_pool) def consumer():
while True:
task = rcon.rpop("queue")
if not task:
time.sleep(1)
continue
asyncio.run_coroutine_threadsafe(do_sleep(int(task), queue), new_loop) if __name__ == '__main__':
print(time.ctime())
new_loop = asyncio.new_event_loop() # 定义一个线程,运行一个事件循环对象,用于实时接收新任务
loop_thread = Thread(target=start_loop, args=(new_loop,))
loop_thread.setDaemon(True)
loop_thread.start()
# 创建redis连接
rcon = get_redis() queue = Queue() # 子线程:用于消费队列消息,并实时往事件对象容器中添加新任务
consumer_thread = Thread(target=consumer)
consumer_thread.setDaemon(True)
consumer_thread.start() while True:
msg = queue.get()
print("协程运行完..")
print("当前时间:", time.ctime())

稍微讲下代码

loop_thread:单独的线程,运行着一个事件对象容器,用于实时接收新任务。
consumer_thread:单独的线程,实时接收来自Redis的消息队列,并实时往事件对象容器中添加新任务。

输出结果

Thu May 31 23:42:48 2018
协程运行完..
当前时间: Thu May 31 23:42:49 2018 协程运行完..
当前时间: Thu May 31 23:42:51 2018 协程运行完..
当前时间: Thu May 31 23:42:53 2018

我们在Redis,分别发起了5s3s1s的任务。
从结果来看,这三个任务,确实是并发执行的,1s的任务最先结束,三个任务完成总耗时5s

运行后,程序是一直运行在后台的,我们每一次在Redis中输入新值,都会触发新任务的执行。。


												

python 并发专题(十四):asyncio (三)实战的更多相关文章

  1. python 并发专题(四):yield以及 yield from

    一.yield python中yield的用法很像return,都是提供一个返回值,但是yield和return的最大区别在于,return一旦返回,则代码段执行结束,但是yield在返回值以后,会交 ...

  2. 孤荷凌寒自学python第八十四天搭建jTessBoxEditor来训练tesseract模块

    孤荷凌寒自学python第八十四天搭建jTessBoxEditor来训练tesseract模块 (完整学习过程屏幕记录视频地址在文末) 由于本身tesseract模块针对普通的验证码图片的识别率并不高 ...

  3. 孤荷凌寒自学python第七十四天开始写Python的第一个爬虫4

    孤荷凌寒自学python第七十四天开始写Python的第一个爬虫4 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 直接上代码.详细过程见文末屏幕录像 ...

  4. 「kuangbin带你飞」专题十四 数论基础

    layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...

  5. 孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3

    孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十天. 今天继续学习mongoDB的简单操作, ...

  6. 孤荷凌寒自学python第五十四天使用python来删除Firebase数据库中的文档

    孤荷凌寒自学python第五十四天使用python来删除Firebase数据库中的文档 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数据库 ...

  7. 进击的Python【第十四章】:Web前端基础之Javascript

    进击的Python[第十四章]:Web前端基础之Javascript 一.javascript是什么 JavaScript 是一种轻量级的编程语言. JavaScript 是可插入 HTML 页面的编 ...

  8. 开发指南专题十四:JEECG微云高速开发平台MiniDao 介绍

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhangdaiscott/article/details/27068645   开发指南专题十四:J ...

  9. 六十四 asyncio

    asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持. asyncio的编程模型就是一个消息循环.我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要 ...

  10. python 教程 第十四章、 地址薄作业

    第十四章. 地址薄作业 #A Byte of Python #!/usr/bin/env python import cPickle import os #define the contacts fi ...

随机推荐

  1. [noi.ac省选模拟赛20200606]赌怪

    题目   点这里看题目. 分析   先特判掉\(K=2\)的情况.   首先可以考虑到一个简单 DP :   \(f(i)\):前\(i\)张牌的最大贡献.   转移可以\(O(n^2)\)地枚举区间 ...

  2. [FireDAC][Phys][MSSQL]-310._数据库安装工具_问题需要解决_连载_3

    //先来看看我们碰到的问题,再来求解答SQL脚本执行失败,[FireDAC][Phys][MSSQL]-310. Cannot execute command returning result set ...

  3. (五)POI-设置单元格的对齐方式

    原文链接:https://blog.csdn.net/class157/article/details/92817149 package com.java.poi; import org.apache ...

  4. WeChair项目Beta冲刺(9/10)

    团队项目进行情况 1.昨日进展    Beta冲刺第九天 昨日进展: 项目开始扫尾 2.今日安排 前端:前端工作已经完成 后端:扫码占座后端测试,实现对超时预约座位下座的功能 数据库:和后端组织协商扫 ...

  5. 尚硅谷 dubbo学习视频

    1 1.搭建zookpeer注册中心 windows下载zooker  需要修改下zoo_sample .cfg为zoo.cnf 然后需要zoo.cnf中数据文件的路径 第五步:把zoo_sample ...

  6. Python元类实战,通过元类实现数据库ORM框架

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第19篇文章,我们一起来用元类实现一个简易的ORM数据库框架. 本文主要是受到了廖雪峰老师Python3入门教程的启 ...

  7. 入门大数据---通过Yarn搭建MapReduce和应用实例

    上一篇中我们了解了MapReduce和Yarn的基本概念,接下来带领大家搭建下Mapreduce-HA的框架. 结构图如下: 开始搭建: 一.配置环境 注:可以现在一台计算机上进行配置,然后分发给其它 ...

  8. html+css快速入门教程(4)

    练习 1.网易考拉下拉菜单 2.爱奇艺新闻 3.ps滤镜菜单 4.爱奇艺列表 7 布局 7.1 盒子模型 网页设计,首先要做好整体的布局,网页布局就是将不同的元素按照一定的规则放置在浏览器的不同位置, ...

  9. 打开指定大小的新窗口和window.open参数

    用法: <SCRIPT LANGUAGE="javascript">   window.open ('要打开的路径', '窗口名称', '参数列表');</SCR ...

  10. 比Minikube更快,使用Kind快速创建K8S学习环境

    简述 K8S 如火如荼的发展着,越来越多人想学习和了解 K8S,但是由于 K8S 的入门曲线较高很多人望而却步. 然而随着 K8S 生态的蓬勃发展,社区也呈现了越来越多的部署方案,光针对生产可用的环境 ...