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

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

也即:

在主线程里,一个无限循环,一个不断加入的新任务协程:

一个loop.run_forever(),一个async def do_sleep2(x, queue, msg=""):

子线程作消费者。(代码里没有演示,只是用子线程有循环事件和异步加入协程,主线程循环结果)

import time
import asyncio
from queue import Queue
from threading import Thread
from asyncio.futures import Future
from collections.abc import Coroutine, Generator

"""
只要在一个生成器函数头部用上 @asyncio.coroutine 装饰器
就能将这个函数对象,【标记】为协程对象。注意这里是【标记】,划重点。
实际上,它的本质还是一个生成器。
标记后,它实际上已经可以当成协程使用。
"""

@asyncio.coroutine
def hello2():
    yield from asyncio.sleep(1)

coroutine2 = hello2()
print(isinstance(coroutine2, Generator))
print(isinstance(coroutine2, Coroutine))
# True
# False
"""
只要在一个函数前面加上 async 关键字,这个函数对象是一个协程,
通过isinstance函数,它确实是Coroutine类型。
"""

async def hello(name):
    print("Hello, ", name)
    time.sleep(2)
    return 'stop 2 seconds.'

# 定义协程对象
coroutine = hello("world")
print(isinstance(coroutine, Coroutine))
# True

# 定义事件循环对象容器
loop = asyncio.get_event_loop()

# 将协程转为task任务
# task = asyncio.ensure_future(coroutine)
task = loop.create_task(coroutine)
print(isinstance(task, Future))
# True
# 将task任务扔进事件循环对象中并触发
loop.run_until_complete(task)

# task.result() 可以取得返回结果
print('return value: {}'.format(task.result()))
# Hello,  world
# return value: stop 2 seconds.

# 协程函数
async def do_some_work(x):
    print('waiting: ', x)
    await asyncio.sleep(x)
    return 'Done after {}s'.format(x)

# 协程对象
coroutine1 = do_some_work(1)
coroutine2 = do_some_work(2)
coroutine4 = do_some_work(4)

# 将协程转成task,并组成list
tasks = [
    asyncio.ensure_future(coroutine1),
    asyncio.ensure_future(coroutine2),
    asyncio.ensure_future(coroutine4),
]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
# loop.run_until_complete(asyncio.gather(*tasks))

for task in tasks:
    print('Task ret: ', task.result())
# waiting:  1
# waiting:  2
# waiting:  4
# Task ret:  Done after 1s
# Task ret:  Done after 2s
# Task ret:  Done after 4s

# 外部的协程函数
async def main():
    coroutine1 = do_some_work(1)
    coroutine2 = do_some_work(2)
    coroutine4 = do_some_work(4)

    tasks = [
        asyncio.ensure_future(coroutine1),
        asyncio.ensure_future(coroutine2),
        asyncio.ensure_future(coroutine4),
    ]

    # 【重点】:await 一个task列表(协程)
    # dones:表示已经完成的任务
    # pendings:表示未完成的任务
    dones, pendings = await asyncio.wait(tasks)

    for task in dones:
        print('Task ret: ', task.result())

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# waiting:  1
# waiting:  2
# waiting:  4
# Task ret:  Done after 1s
# Task ret:  Done after 2s
# Task ret:  Done after 4s

"""
协程中的状态

Pending:悬而未决的状态
Running:事件循环正在调用执行任务
Done:任务执行完毕
Cancelled:Task被取消后的状态

asyncio.wait:接收形式少点,控制性强,手工循环结果。

asyncio.gather:接收形式广泛,直接返回结果。
"""

def start_loop(loop):
    # 一个在后台永远运行的事件循环
    asyncio.set_event_loop(loop)
    loop.run_forever()

def start_loop2(loop):
    # 一个在后台永远运行的事件循环
    asyncio.set_event_loop(loop)
    loop.run_forever()

def do_sleep(x, queue, msg=""):
    time.sleep(x)
    queue.put(msg)

async def do_sleep2(x, queue, msg=""):
    await asyncio.sleep(x)
    queue.put(msg)

queue = Queue()
queue2 = Queue()
new_loop = asyncio.new_event_loop()
new_loop2 = asyncio.new_event_loop()

t = Thread(target=start_loop, args=(new_loop, ))
t.start()

t2 = Thread(target=start_loop2, args=(new_loop2, ))
t2.start()

print(time.ctime())

# 动态添加两个协程
# 这种方法,在主线程是同步的
new_loop.call_soon_threadsafe(do_sleep, 6, queue, "第一个")
new_loop.call_soon_threadsafe(do_sleep, 6, queue, "第二个")

# 动态添加两个协程
# 这种方法,在主线程是异步的
asyncio.run_coroutine_threadsafe(do_sleep2(6, queue, "第1个"), new_loop2)
asyncio.run_coroutine_threadsafe(do_sleep2(6, queue, "第2个"), new_loop2)

while True:
    msg = queue.get()
    print("{} 协程运行完成。。。".format(msg))
    print(time.ctime())

# Thu Dec 27 19:51:00 2018
# 第一个 协程运行完成。。。
# Thu Dec 27 19:51:06 2018
# 第二个 协程运行完成。。。
# Thu Dec 27 19:51:12 2018

while True:
    msg = queue2.get()
    print("{} 协程运行完成。。。".format(msg))
    print(time.ctime())

# 第1个 协程运行完成。。。
# Thu Dec 27 20:02:10 2018
# 第2个 协程运行完成。。。
# Thu Dec 27 20:02:10 2018

async/await套路编程的更多相关文章

  1. 【转】C# Async/Await 异步编程中的最佳做法

    Async/Await 异步编程中的最佳做法 Stephen Cleary 近日来,涌现了许多关于 Microsoft .NET Framework 4.5 中新增了对 async 和 await 支 ...

  2. 【转】以Python为例的Async / Await的编程基础

    转, 原文:https://www.cnblogs.com/middleware/p/11996731.html 以Python为例的Async / Await的编程基础 -------------- ...

  3. .NET Web应用中为什么要使用async/await异步编程

    前言 什么是async/await? await和async是.NET Framework4.5框架.C#5.0语法里面出现的技术,目的是用于简化异步编程模型. async和await的关系? asy ...

  4. C#中 Thread,Task,Async/Await 异步编程

    什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调 ...

  5. async/await 异步编程(转载)

    转载地址:http://www.cnblogs.com/teroy/p/4015461.html 前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入 ...

  6. async/await 异步编程

    前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入的,由于之前对于异步编程不是很了解,所以花费了一些时间学习一下相关的知识,并整理成这篇博客,如果在 ...

  7. c# 关于async/await异步编程的浅析和使用

    线程的同步运行,时效性慢,异步运行,时效性快! 在c#5.0引出了async/await关键字,可以用其来进行异步编程. async/await定义异步方法的语法如下: 1.在方法的返回类型前面加上a ...

  8. .NET 中的 async/await 异步编程

    原文出处: Teroy 的博客 前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入的,由于之前对于异步编程不是很了解,所以花费了一些时间学习一下相关 ...

  9. 以Python为例的Async / Await的编程基础

    来源:Redislabs 作者:Loris Cro 翻译:Kevin (公众号:中间件小哥) 近年来,许多编程语言都在努力改进它们的并发原语.Go 语言有 goroutines,Ruby 有 fibe ...

随机推荐

  1. java实现获取当前年月日 小时 分钟 秒 毫秒

    java代码实现如下 view source print?     /**      * 英文简写(默认)如:2010-12-01      */     public static String F ...

  2. HDU - 3980 Paint Chain(SG函数)

    https://vjudge.net/problem/HDU-3980 题意 一串长度为n的柱子,每个人只能给连续的珠子涂色,涂过的不能再涂,不能涂的人就输了,问最后谁获胜. 分析 第一个人先涂m个, ...

  3. Git与GitHub学习笔记(五)一次提交失败的记录

    代码已经跟踪了,添加注释说明,但是总是添加不了 error: pathspec 'live-page'' did not match any file(s) known to git. 重复了好多遍, ...

  4. POJ1287 Networking【最小生成树】

    题意: 给出n个节点,再有m条边,这m条边代表从a节点到b节点电缆的长度,现在要你将所有节点都连起来,并且使长度最小 思路: 这是个标准的最小生成树的问题,用prim的时候需要注意的是他有重边,取边最 ...

  5. HTML5的学习(一)HTML5标签

    HTML5是WHATWG与W3C合作,创建的一个新版本的HTML.2014年10月29日,万维网联盟宣布,经过接近8年的艰苦努力,该标准规范终于制定完成.HTML5相比于之前的HTML的其他版本增加了 ...

  6. HTTP协议-响应报文格式

    HTTP协议-响应码 浏览器向服务器发出请求,服务器处理可能是成功.可能是失败.可能没有权限访问等原因,服务器会通过响应码来告诉浏览器处理结果. " : OK " : Found ...

  7. C++获取当前所有进程的完整路径

    实现代码 #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <st ...

  8. 【vim】删除标记内部的文字 di[标记]

    当我开始使用 Vim 时,一件我总是想很方便做的事情是如何轻松的删除方括号或圆括号里的内容.转到开始的标记,然后使用下面的语法: di[标记] 比如,把光标放在开始的圆括号上,使用下面的命令来删除圆括 ...

  9. C# 清理消息管道的消息

    using System;using System.Collections.Generic;using System.Linq;using System.Messaging;using System. ...

  10. VC++常用数据类型及其操作详解

    原文地址:http://blog.csdn.net/ithomer/article/details/5019367 VC++常用数据类型及其操作详解 一.VC常用数据类型列表 二.常用数据类型转化 2 ...