请选择 进入手机版 | 继续访问电脑版
楼主: mebusw
671 0

[原创博文] 利用python yielding创建协程将异步编程同步化 [推广有奖]

  • 0关注
  • 0粉丝

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
19 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
230 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2020-2-11
最后登录
2020-2-12

mebusw 发表于 2020-2-12 10:09:56 |显示全部楼层 |坛友微信交流群

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
  • 目录
    • 回顾同步与异步编程
    • 回顾多线程编程
    • yield与协程
    • 异步编程同步化
    回顾同步与异步编程

    同步编程即线性化编程,代码按照既定顺序执行,上一条语句执行完才会执行下一条,否则就一直等在那里。
    但是许多实际操作都是CPU 密集型任务和 IO 密集型任务,比如网络请求,此时不能让这些任务阻塞主线程的工作,于是就会采用异步编程。

    异步的标准元素就是回调函数(Callback, 后来衍生出Promise/Deferred概念),主线程发起一个异步任务,让其自己到一边去工作,当其完成后,会通过执行预先指定的回调函数完成后续任务,然后返回主线程。在异步任务执行过程中,主线程无需等待和阻塞,可以继续处理其他任务。

    下例大家并不陌生,是jQuery标准发送http异步请求的方式。

    1
    2
    3
    4
    5
    6
    7
    $.ajax({
        url:"/echo/json/",
        success: function(response)
        {
           console.info(response.name);
        }
    });

    而并发的核心思想在于,大的任务可以分解成一系列的子任务,后者可以被调度成 同时执行或异步执行,而不是一次一个地或者同步地执行。两个子任务之间的 切换也就是上下文切换。

    回顾多线程编程

    当主线程发起异步任务,这个任务跑到哪里去工作了呢?这就说到多线程(包括多进程)编程,一个主线程可以主动创建多个子线程,然后将任务交给子线程,每个子线程拥有自己的堆栈空间。操作系统可以通过分时的方式让同一个CPU轮流调度各个线程,编程人员无需关心操作系统是如何工作的。

    但是如果需要在多个线程之间通信,则需要编程人员自己写代码来控制线程之间的协作(利用锁或信号量)以及通信(利用管道、队列等)。

    经典的Producer-Consumer问题

    这个问题说的是有两方进行通信和协作,一方只负责生产内容,另一方只负责消费内容。消费者并不知道,也无需知道生产者何时生产,只是当有内容生产出来负责消费即可,没有内容时就等待。这是一个经典的异步问题。

    Threading/Queue方案

    传统的解决方案即是采用多线程来实现,生产者和消费者分别处于不同的线程或进程中,由操作系统进行调度。来看一篇经典的多线程教程中的例子,是不是很像Java风格?—啰嗦。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    import threading
    import time
    import logging
    import random
    import Queue

    logging.basicConfig(level=logging.DEBUG,
                        format='(%(threadName)-9s) %(message)s',)

    BUF_SIZE = 10
    q = Queue.Queue(BUF_SIZE)

    class ProducerThread(threading.Thread):
        def __init__(self, group=None, target=None, name=None,
                     args=(), kwargs=None, verbose=None):
            super(ProducerThread,self).__init__()
            self.target = target
            self.name = name

        def run(self):
            while True:
                if not q.full():
                    item = random.randint(1,10)
                    q.put(item)
                    logging.debug('Putting ' + str(item)  
                                  + ' : ' + str(q.qsize()) + ' items in queue')
                    time.sleep(random.random())
            return

    class ConsumerThread(threading.Thread):
        def __init__(self, group=None, target=None, name=None,
                     args=(), kwargs=None, verbose=None):
            super(ConsumerThread,self).__init__()
            self.target = target
            self.name = name
            return

        def run(self):
            while True:
                if not q.empty():
                    item = q.get()
                    logging.debug('Getting ' + str(item)
                                  + ' : ' + str(q.qsize()) + ' items in queue')
                    time.sleep(random.random())
            return

    if __name__ == '__main__':
       
        p = ProducerThread(name='producer')
        c = ConsumerThread(name='consumer')

        p.start()
        time.sleep(2)
        c.start()
        time.sleep(2)
    MessageQueue方案

    基于多线程方案,这个问题已经演变成消息中介模式(有些公司喜欢称之为”邮局”),有各种的商业MQ方案可以直接使用。

    这里以RabbitMQ开源方案为例,Producer一方向名为队列中发送”Hello World!”内容,而Consumer一方则监听队列,当有内容进入队列时,就执行callback函数来收取并处理内容。发送与收取的动作是异步执行的,互不干扰。


(论坛帖子长度限制,后半段待续或见https://www.jackyshen.com/2015/0 ... th-python-yielding/

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝


已有 2 人评分经验 收起 理由
cheetahfly + 100 精彩帖子
yunnandlg + 80 精彩帖子

总评分: 经验 + 180   查看全部评分

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-3-29 13:11