zoukankan      html  css  js  c++  java
  • python并发编程之进程池,线程池

    要注意一下
    不能无限的开进程,不能无限的开线程
    最常用的就是开进程池,开线程池。其中回调函数非常重要
    回调函数其实可以作为一种编程思想,谁好了谁就去掉
    只要你用并发,就会有锁的问题,但是你不能一直去自己加锁吧
    那么我们就用QUEUE,这样还解决了自动加锁的问题
    由Queue延伸出的一个点也非常重要的概念。以后写程序也会用到
    这个思想。就是生产者与消费者问题

    一、Python标准模块--concurrent.futures(并发未来)

    concurent.future模块需要了解的
    1.concurent.future模块是用来创建并行的任务,提供了更高级别的接口,
    为了异步执行调用
    2.concurent.future这个模块用起来非常方便,它的接口也封装的非常简单
    3.concurent.future模块既可以实现进程池,也可以实现线程池
    4.模块导入进程池和线程池
    from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
    还可以导入一个Executor,但是你别这样导,这个类是一个抽象类
    抽象类的目的是规范他的子类必须有某种方法(并且抽象类的方法必须实现),但是抽象类不能被实例化
    5.
    p = ProcessPoolExecutor(max_works)对于进程池如果不写max_works:默认的是cpu的数目,默认是4个
    p = ThreadPoolExecutor(max_works)对于线程池如果不写max_works:默认的是cpu的数目*5
    6.如果是进程池,得到的结果如果是一个对象。我们得用一个.get()方法得到结果
    但是现在用了concurent.future模块,我们可以用obj.result方法
    p.submit(task,i) #相当于apply_async异步方法
    p.shutdown() #默认有个参数wite=True (相当于close和join)

    二、线程池

    进程池:就是在一个进程内控制一定个数的线程
    基于concurent.future模块的进程池和线程池 (他们的同步执行和异步执行是一样的)
    1 # 1.同步执行--------------
     2 from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
     3 import os,time,random
     4 def task(n):
     5     print('[%s] is running'%os.getpid())
     6     time.sleep(random.randint(1,3))  #I/O密集型的,,一般用线程,用了进程耗时长
     7     return n**2
     8 if __name__ == '__main__':
     9     start = time.time()
    10     p = ProcessPoolExecutor()
    11     for i in range(10): #现在是开了10个任务, 那么如果是上百个任务呢,就不能无线的开进程,那么就得考虑控制
    12         # 线程数了,那么就得考虑到池了
    13         obj  = p.submit(task,i).result()  #相当于apply同步方法
    14     p.shutdown()  #相当于close和join方法
    15     print('='*30)
    16     print(time.time() - start)  #17.36499309539795
    17 
    18 
    19 # 2.异步执行-----------
    20 # from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
    21 # import os,time,random
    22 # def task(n):
    23 #     print('[%s] is running'%os.getpid())
    24 #     time.sleep(random.randint(1,3))  #I/O密集型的,,一般用线程,用了进程耗时长
    25 #     return n**2
    26 # if __name__ == '__main__':
    27 #     start = time.time()
    28 #     p = ProcessPoolExecutor()
    29 #     l = []
    30 #     for i in range(10): #现在是开了10个任务, 那么如果是上百个任务呢,就不能无线的开进程,那么就得考虑控制
    31 #         # 线程数了,那么就得考虑到池了
    32 #         obj  = p.submit(task,i)  #相当于apply_async()异步方法
    33 #         l.append(obj)
    34 #     p.shutdown()  #相当于close和join方法
    35 #     print('='*30)
    36 #     print([obj.result() for obj in l])
    37 #     print(time.time() - start)  #5.362306594848633
    基于concurrent.futures模块的进程池
    1 from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
     2 from threading import currentThread
     3 import os,time,random
     4 def task(n):
     5     print('%s:%s is running'%(currentThread().getName(),os.getpid()))  #看到的pid都是一样的,因为线程是共享了一个进程
     6     time.sleep(random.randint(1,3))  #I/O密集型的,,一般用线程,用了进程耗时长
     7     return n**2
     8 if __name__ == '__main__':
     9     start = time.time()
    10     p = ThreadPoolExecutor() #线程池 #如果不给定值,默认cup*5
    11     l = []
    12     for i in range(10):  #10个任务 # 线程池效率高了
    13         obj  = p.submit(task,i)  #相当于apply_async异步方法
    14         l.append(obj)
    15     p.shutdown()  #默认有个参数wite=True (相当于close和join)
    16     print('='*30)
    17     print([obj.result() for obj in l])
    18     print(time.time() - start)  #3.001171827316284
    基于concurrent.futures模块的线程池

    应用线程池

    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    import requests
    import time,os
    def get_page(url):
        print('<%s> is getting [%s]'%(os.getpid(),url))
        response = requests.get(url)
        if response.status_code==200:  #200代表状态:下载成功了
            return {'url':url,'text':response.text}
    def parse_page(res):
        res = res.result()
        print('<%s> is getting [%s]'%(os.getpid(),res['url']))
        with open('db.txt','a') as f:
            parse_res = 'url:%s size:%s
    '%(res['url'],len(res['text']))
            f.write(parse_res)
    if __name__ == '__main__':
        # p = ThreadPoolExecutor()
        p = ProcessPoolExecutor()
        l = [
            'http://www.baidu.com',
            'http://www.baidu.com',
            'http://www.baidu.com',
            'http://www.baidu.com',
        ]
        for url in l:
            res = p.submit(get_page,url).add_done_callback(parse_page) #这里的回调函数拿到的是一个对象。得
            #  先把返回的res得到一个结果。即在前面加上一个res.result() #谁好了谁去掉回调函数
                                    # 回调函数也是一种编程思想。不仅开线程池用,开线程池也用
        p.shutdown()  #相当于进程池里的close和join
        print('',os.getpid())

    map函数的应用

    # map函数举例
    obj= map(lambda x:x**2 ,range(10))
    print(list(obj))
    
    #运行结果[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    1 # 我们的那个p.submit(task,i)和map函数的原理类似。我们就
     2 # 可以用map函数去代替。更减缩了代码
     3 from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
     4 import os,time,random
     5 def task(n):
     6     print('[%s] is running'%os.getpid())
     7     time.sleep(random.randint(1,3))  #I/O密集型的,,一般用线程,用了进程耗时长
     8     return n**2
     9 if __name__ == '__main__':
    10     p = ProcessPoolExecutor()
    11     obj = p.map(task,range(10))
    12     p.shutdown()  #相当于close和join方法
    13     print('='*30)
    14     print(obj)  #返回的是一个迭代器
    15     print(list(obj))
    map函数应用
  • 相关阅读:
    软件测试的常阅博客
    使用Silverlight操作ASPNETDB数据库
    在Silverlight中实现跨域访问
    部署Silverlight应用时遇到的问题
    如何在WPF和Silverlight中取得DataTemplate中的命名元素
    [转] Silverlight Navigation(多页面切换、传值)
    如何让Button点击后不得focus
    VS2010无法连接到SQlServer2008 Database file
    常用的gulp插件
    Android通过http协议POST传输方式
  • 原文地址:https://www.cnblogs.com/lujiacheng-Python/p/10293733.html
Copyright © 2011-2022 走看看