zoukankan      html  css  js  c++  java
  • (十)异步调用与回调机制

    一、同步调用


    提交任务有两种方式:同步调用,异步调用。

    同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果再执行下一行代码,导致程序是串行执行。

    例子:今年你们公司开年会,举办了一个吃汉堡大赛,然后把计算下大家一共吃了多少个,谁的最多,谁发的年终奖就最多。

    # 1,同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果再执行下一行代码,导致程序是串行执行。
    from concurrent.futures import ThreadPoolExecutor
    import time,random
    
    def eat(name):
        print("%s 正在吃。" % name)
        time.sleep(random.randint(3,5))     # 吃的时间
        res = random.randint(7,13)          # 吃了几个
        return {"name":name,"res":res}
    
    def count(hamburger):
        name = hamburger["name"]
        num = hamburger["res"]
        print("%s 吃了《%s》个。" % (name,num))
    
    if __name__ == '__main__':
        pool = ThreadPoolExecutor(3)    # 参赛人数,用线程池
    
        shit1 = pool.submit(eat,"托儿所").result()   # 提交任务,等待任务执行完毕,拿到结果
        count(shit1)
        shit2 = pool.submit(eat,"儿童劫").result()
        count(shit2)
        shit3 = pool.submit(eat,"瑞萌萌").result()
        count(shit3)
    
    """
    托儿所 正在吃。
    托儿所 吃了《8》个。
    儿童劫 正在吃。
    儿童劫 吃了《12》个。
    瑞萌萌 正在吃。
    瑞萌萌 吃了《8》个。
    """

    二、异步调用与回调函数


    异步调用:提交完任务后,不在原地等待任务执行完毕。

    回调函数:可以为进程池或线程池内的每个进程或线程绑定一个函数,该函数在进程或线程的任务执行完毕后自动触发,并接收任务的返回值当作参数,该函数称为回调函数。

    # 2,异步调用:提交完任务后,不在原地等待任务执行完毕,
    from concurrent.futures import ThreadPoolExecutor
    import time,random
    
    def eat(name):
        print("%s 正在吃。" % name)
        time.sleep(random.randint(3,5))     # 吃的时间
        res = random.randint(7,13)          # 吃几个
        return {"name":name,"res":res}
        # weight({"name":name,"res":res})   # 这样写的话,相当于把两个函数写到一起了,耦合了,而我们是要解耦合的
    
    def count(hamburger):
        hamburger = hamburger.result()    # 这里的hamburger拿到的是一个对象
        name = hamburger["name"]
        num = hamburger["res"]
        print("%s 吃了《%s》个." % (name,num))
    
    if __name__ == '__main__':
        pool = ThreadPoolExecutor(3)    # 参赛人数,用线程池
    
        # 回调函数是在,前面的函数执行完,有返回值了,自动触发这个功能,把前面的对象直接当参数传给weight
        pool.submit(eat,"托儿所").add_done_callback(count)     # 前面是对象,后面的是回调函数
        pool.submit(eat,"儿童劫").add_done_callback(count)
        pool.submit(eat,"瑞萌萌").add_done_callback(count)
        # count拿到的是一个future对象obj,需要用obj.result()拿到结果,也就是 hamburger.result()
    
    """
    托儿所 正在吃。
    儿童劫 正在吃。
    瑞萌萌 正在吃。
    瑞萌萌 吃了《12》个.
    托儿所 吃了《12》个.
    儿童劫 吃了《11》个.
    """

    三、练习


    在程序当中模拟浏览器的行为

    from concurrent.futures import ThreadPoolExecutor
    import requests     # 在程序当中模拟浏览器的行为,要用到这个模块
    import time
    
    def get(url):
        print("GET %s." % url)
        # requests.get 实际上就是去目标站,下载一个文件到本地
        response = requests.get(url)    # 传上你的额 url地址,它会拿到一个对象
        time.sleep(3)
        return {"url":url,"content":response.text}      # text这个属性得到的是网页内容
    
    def parse(res):
        """解析网页信息"""
        # 正则表达式,解析出你想要的内容
        # 爬虫项目基本原理:先把内容(字符串)下载下来,再对内容进行处理得到自己想要的部分。
        res = res.result()
        print("%s parse res is %s." % (res["url"],len(res["content"])))
    
    
    if __name__ == '__main__':
        urls = [
            "https://www.cnblogs.com/zoling7",
            "https://www.baidu.com",
            "https://www.huya.com",
        ]
    
        pool = ThreadPoolExecutor(2)
    
        for url in urls:
            pool.submit(get,url).add_done_callback(parse)
    
    """
    GET https://www.cnblogs.com/zoling7.
    GET https://www.baidu.com.
    https://www.baidu.com parse res is 2443.
    GET https://www.huya.com.
    https://www.cnblogs.com/zoling7 parse res is 15181.
    https://www.huya.com parse res is 397258.
    """
  • 相关阅读:
    绘制程序流程图笔记
    强软弱虚引用
    安全点和安全区域
    垃圾回收算法
    垃圾回收相关算法
    内存访问全过程
    多级页表与快表
    分页
    虚拟内存
    内存分段机制
  • 原文地址:https://www.cnblogs.com/zoling7/p/13397494.html
Copyright © 2011-2022 走看看