python 并发 ThreadPool

发布时间:2019-09-09 08:43:12编辑:auto阅读(1872)

    asyncio基础

    asyncio协程

    asyncio并发下载

    asyncio, aiohttp爬虫    -> 这里写了一些原理和使用asyncio需要注意的东西, 对asyncio 有些基础的可以看看

    python asyncio aiohttp 异步下载 完整例子

    用 c / c++ 分别实现的简单线程池  ->对线程池实现有兴趣的可以看看

    正文:

    Executor是一个抽象类,子类:

    ThreadPoolExecutorProcessPoolExecutor ,一个线程池,一个进程池.

    future对象:在未来的某一时刻完成操作的对象.

    submit方法可以返回一个future对象,此对象直接返回,等线程函数执行完后把return的数据再set_result到future对象中; 

    下面实现了submit, map 与 as_completed的差别 , 下面的例子中都没有使用with ,实际使用时需要调用shutdown , 或用with

     

     

    #线程执行的函数
    def add(n1,n2):
        v = n1 + n2
        print('add :', v , ', tid:',threading.currentThread().ident)
        time.sleep(n1)
        return v
    #通过submit把需要执行的函数扔进线程池中.
    #submit 直接返回一个future对象
    ex = ThreadPoolExecutor(max_workers=3)      #制定最多运行N个线程
    f1 = ex.submit(add,2,3)
    f2 = ex.submit(add,2,2)
    print('main thread running')
    print(f1.done())                            #done 看看任务结束了没
    print(f1.result())                          #获取结果 ,阻塞方法

     

     注意 map 方法,返回是跟你提交序列是一致的. 是有序的

     

    #下面是map 方法的简单使用.  注意:map 返回是一个生成器 ,并且是*有序的*
    URLS = ['http://www.baidu.com', 'http://www.qq.com', 'http://www.sina.com.cn']
    def get_html(url):
        print('thread id:',threading.currentThread().ident,' 访问了:',url)
        return requests.get(url)            #这里使用了requests 模块
    ex = ThreadPoolExecutor(max_workers=3)
    res_iter = ex.map(get_html,URLS)        #内部迭代中, 每个url 开启一个线程
    for res in res_iter:                    #此时将阻塞 , 直到线程完成或异常
        print('url:%s ,len: %d'%(res.url,len(res.text)))

     

    接下来,使用as_completed . 这个函数为submit 而生, 为啥呢?

     

    你总想通过一种办法来解决submit后啥时候完成的吧 , 而不是一次次调用future.done 或者 使用 future.result 吧.

    concurrent.futures.as_completed(fstimeout=None) 返回一个生成器,在迭代过程中会阻塞,

    直到线程完成或者异常时,返回一个被set_result的Future对象.

    同时注意, map方法返回是有序的, as_completed 是那个线程先完成/失败 就返回

    #这是一个简单的 as_completed
    URLS = ['http://www.baidu.com', 'http://www.qq.com', 'http://www.sina.com.cn']
    def get_html(url):
        time.sleep(3)
        print('thread id:',threading.currentThread().ident,' 访问了:',url)
        return requests.get(url)            #这里使用了requests 模块
    ex = ThreadPoolExecutor(max_workers=3)
    f = ex.submit(get_html,URLS[0])          #提交一个任务,放入线程池中,准备执行
    print('main thread running')
    for future in as_completed([f]):        #as_completed()接受一个可迭代的Future序列,返回一个生成器,在完成或异常时返回这个Future对象
        print('一个任务完成.')
        print(future.result())
    #as_completed 完整的例子
    #as_completed 返回一个生成器,用于迭代, 一旦一个线程完成(或失败) 就返回
    URLS = ['http://www.baidu.com', 'http://www.qq.com', 'http://www.sina.com.cn']
    def get_html(url):
        time.sleep(1)
        print('thread id:',threading.currentThread().ident,' 访问了:',url)
        return requests.get(url)            #这里使用了requests 模块
    ex = ThreadPoolExecutor(max_workers=3)   #最多3个线程
    future_tasks = [ex.submit(get_html,url) for url in URLS]    #创建3个future对象
    for future in as_completed(future_tasks):       #迭代生成器
        try:
            resp = future.result()
        except Exception as e:
            print('%s'%e)
        else:
            print('%s has %d bytes!'%(resp.url, len(resp.text)))
    """
    thread id: 5160  访问了: http://www.baidu.com
    thread id: 7752  访问了: http://www.sina.com.cn
    thread id: 5928  访问了: http://www.qq.com
    http://www.qq.com/ has 240668 bytes!
    http://www.baidu.com/ has 2381 bytes!
    https://www.sina.com.cn/ has 577244 bytes!
    """

     

     wait 是阻塞函数,第一个参数和as_completed一样, 一个可迭代的future序列,返回一个元组 ,包含2个set , 一个完成的,一个未完成的

     

    """
    wait 例子
    参数:
        FIRST_COMPLETED    当任何未来完成或被取消时,该函数将返回。
        
        FIRST_EXCEPTION    当任何未来通过提出异常完成时,函数将返回。如果没有未来引发异常,那么它等同于 ALL_COMPLETED。
        
        ALL_COMPLETED(默认)      当所有future完成或被取消时,函数将返回。
    """
    URLS = ['http://www.baidu.com', 'http://www.qq.com', 'http://www.sina.com.cn']
    def get_html(url):
        time.sleep(1)
        print('thread id:',threading.currentThread().ident,' 访问了:',url)
        return requests.get(url)            #这里使用了requests 模块
    ex = ThreadPoolExecutor(max_workers=3)   #最多3个线程
    future_tasks = [ex.submit(get_html,url) for url in URLS]    #创建3个future对象
    try:
        result = wait(future_tasks,return_when = fu.FIRST_COMPLETED)
        done_set = result[0]
        for future in done_set:
            resp = future.result()
            print('第一个网页任务完成 url:%s , len:%d bytes! ' % (resp.url, len(resp.text)))
    except Exception as e:
        print('exception :' , e)

     

    最后说一下回调:add_done_callback(fn) , 回调函数是在调用线程完成后再调用的,在同一个线程中.

     

    import os,sys,time,requests,threading
    from concurrent import futures
    
    
    URLS = [
            'http://baidu.com',
            'http://www.qq.com',
            'http://www.sina.com.cn'
            ]
    
    def load_url(url):
        print('tid:',threading.currentThread().ident,',url:',url)
        with requests.get(url) as resp:
            return resp.content
    def call_back(obj):
        print('->>>>>>>>>call_back , tid:',threading.currentThread().ident, ',obj:',obj)
    
    with futures.ThreadPoolExecutor(max_workers=3) as ex:
        # mp = {ex.submit(load_url,url) : url for url in URLS}
        mp = dict()
        for url in URLS:
            f = ex.submit(load_url,url)
            mp[f] = url
            f.add_done_callback(call_back)
        for f in futures.as_completed(mp):
            url = mp[f]
            try:
                data = f.result()
            except Exception as exc:
                print(exc, ',url:',url)
            else:
                print('url:', url, ',len:',len(data),',data[:20]:',data[:20])
    """
    tid: 7128 ,url: http://baidu.com
    tid: 7892 ,url: http://www.qq.com
    tid: 3712 ,url: http://www.sina.com.cn
    ->>>>>>>>>call_back , tid: 7892 ,obj: <Future at 0x2dd64b0 state=finished returned bytes>
    url: http://www.qq.com ,len: 251215 ,data[:20]: b'<!DOCTYPE html>\n<htm'
    ->>>>>>>>>call_back , tid: 3712 ,obj: <Future at 0x2de07b0 state=finished returned bytes>
    url: http://www.sina.com.cn ,len: 577333 ,data[:20]: b'<!DOCTYPE html>\n<!--'
    ->>>>>>>>>call_back , tid: 7128 ,obj: <Future at 0x2d533d0 state=finished returned bytes>
    url: http://baidu.com ,len: 81 ,data[:20]: b'<html>\n<meta http-eq'
    
    """

     

     

     

     

     

     

关键字