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类型
    
  • 相关阅读:
    _mysql.c(42) : fatal error C1083: Cannot open include file: 'config-win.h':问题的解决
    pycharm 插件的升级
    机器学习
    Python三大神器
    印记中文
    Emacs, Nano, or Vim 编辑器“三剑客”
    码云-中国的github
    代码质量管控的四个阶段
    <<创新之路>> 纪录片观后感
    API (Application Programming Interface) 文档大全
  • 原文地址:https://www.cnblogs.com/lav3nder/p/11802328.html
Copyright © 2011-2022 走看看