zoukankan      html  css  js  c++  java
  • 并发编程~~~多线程~~~阻塞,非阻塞,同步,异步, 同步调用,异步调用, 异步调用 + 回调函数

    一 阻塞,非阻塞,同步,异步

    执行的角度:

    阻塞: 程序运行时,遇到IO程序挂起,CPU被切走.

    非阻塞: 程序没有遇到IO或程序遇到IO通过某种手段让cpu强行运行程序.

    提交任务的角度:

    同步: 提交一个任务,自任务开始运行直到此任务结束(可能有IO),返回一个返回值之后,再提交下一个任务.

    异步: 一次提交多个任务,不用等任务结束就可以提交下一个任务.

    二 同步调用,异步调用

    2.1 同步调用:

    from concurrent.futures import ProcessPoolExecutor
    import time,random,os
    def task(i):
        print(f'{os.getpid()}开始任务')
        time.sleep(random.randint(1,3))
        print(f'{os.getpid()}任务结束')
        return i
    
    if __name__ == '__main__':
        pool = ProcessPoolExecutor()
        for i in range(10):
            obj = pool.submit(task,i)
            print(obj.result())
    # obj是一个动态对象,返回的当前的对象状态,有可能在运行,就绪,阻塞,结束.
    # obj.result()必须等任务完成后,返回了结果之后,再执行下一个任务
    

    2.2 异步调用:

    from concurrent.futures import ProcessPoolExecutor
    import time,random,os
    def task(i):
        print(f'{os.getpid()}开始任务')
        time.sleep(random.randint(1,3))
        print(f'{os.getpid()}任务结束')
        return i
    
    if __name__ == '__main__':
        pool = ProcessPoolExecutor()
        for i in range(10):
            pool.submit(task,i)
        pool.shutdown()
        print("主进程")
    # shutdown: 让主进程等待进程池中所有的子进程都结束之后,再执行.在上一个进程池没有完成所有的任务之前,不允许添加新的任务.
    # 一个任务是通过一个函数实现的,任务完成了返回值就是函数的返回值.
    

    2.3 异步调用如何取结果:

    方式一: 统一回收结果

    from concurrent.futures import ProcessPoolExecutor
    import time,random,os
    def task(i):
        print(f'{os.getpid()}开始任务')
        time.sleep(random.randint(1,3))
        print(f'{os.getpid()}任务结束')
        return i
    
    if __name__ == '__main__':
        pool = ProcessPoolExecutor()
        lst = []
        for i in range(10):
            obj = pool.submit(task,i)
            lst.append(obj)
        pool.shutdown(wait=True)
        for k in lst:
            print(k.result())
    # 统一回收结果不能马上收到任何一个已经完成的任务的返回值,只能等所有的任务全部结束后统一回收.
    

    方式二: 异步调用 + 回调函数

    三 异步调用 + 回调函数

    from concurrent.futures import ThreadPoolExecutor
    import requests
    
    def task(url): # 爬取网站数据
        ret = requests.get(url)
        if ret.status_code == 200:
            return ret.text
    
    def parse(obj):
        print(len(obj.result()))
    
    if __name__ == '__main__':
        url_lst = ['http://www.baidu.com',
            'http://www.JD.com',
            'http://www.JD.com',
            'http://www.JD.com',
            'http://www.taobao.com',
            'https://www.cnblogs.com/jin-xin/articles/7459977.html',
            'https://www.luffycity.com/',
            'https://www.cnblogs.com/jin-xin/articles/9811379.html',
            'https://www.cnblogs.com/jin-xin/articles/11245654.html',
            'https://www.sina.com.cn/',]
        pool = ThreadPoolExecutor(4)
    
        for url in url_lst:
            obj = pool.submit(task,url)
            obj.add_done_callback(parse)
    # 异步调用:站在发布任务的角度(并发),处理的是IO类型
    # 回调函数:站在接收结果的角度,按顺序接收每个任务的结果,进行下一步处理,处理的是非IO类型
    
  • 相关阅读:
    jQuery EasyUI API 中文文档 数字框(NumberBox)
    jQuery EasyUI API 中文文档 数值微调器(NumberSpinner)
    jQuery EasyUI API 中文文档 日期时间框(DateTimeBox)
    jQuery EasyUI API 中文文档 微调器(Spinner)
    jQuery EasyUI API 中文文档 树表格(TreeGrid)
    jQuery EasyUI API 中文文档 树(Tree)
    jQuery EasyUI API 中文文档 属性表格(PropertyGrid)
    EntityFramework 数据操作
    jQuery EasyUI API 中文文档 对话框(Dialog)
    jQuery EasyUI API 中文文档 组合表格(ComboGrid)
  • 原文地址:https://www.cnblogs.com/lav3nder/p/11802328.html
Copyright © 2011-2022 走看看