• Python3之并发(六)---线程池


    一、线程池

    系统频繁的启动新线程,线程执行完被销毁,如果线程不能被重复使用,即每个线程都需要经过启动、销毁和运行3个过程,
    这必然会使得系统的性能急剧下降,线程池的意义就在于减少线程创建及消毁过程中损失的系统资源

    线程池在程序运行时创建大量空闲线程,程序只需将要执行的任务交给线程池,线程池就会启动一个空闲的线程来执行,
    当任务执行完后,该线程并不会死亡销毁,而是再次返回到线程池中变成空闲状态,等待一下次被启动

    二、concurrent.futures模块

    concurrent.futures.Executor类
    线程池的基类,不应该直接使用该基类,通过其具体子类使用

    EXecutor类包含两个子类

    concurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())
    用于创建线程池
    max_workers: 线程池中线程的个数,Python3.8版本中,默认min(32, os.cpu_count()+4)
    thread_name_prefix: Python3.6版新增的参数,线程池中启动线程的名字
    initializer,initargs: Python3.7版中新增的参数,初始化线程池的程序和要传入程序的参数
    
    
    concurrent.futures.ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=())
    用于创建进程池
    max_workers: 进程池中进程的个数,默认处理器的个数
    mp_context: Python3.7版中新增的参数,允许用户控制进程池中进程的start_method
    initializer,initargs: 初始化线程池的程序和要传入程序的参数

    线程池对象方法

    ThreadPoolExecutor.submit(fn, *args, **kwargs)
    线程池执行的任务,返回可调用的 Future 对象
    fn: 线程池要执行的函数
    *args: 传递给fn函数的参数
    **kwargs: 关键字形式传递给fn函数的参数
    
    ThreadPoolExecutor.map(func, *iterables, timeout=None, chunksize=1)
    类似于 map(func, *iterables) 函数,启动多个线程以异步方式对 iterables 执行 func
    timeout: 超时时间,int或float类型,超时引发 concurrent.futures.TimeoutError 异常
    
    ThreadPoolExecutor.shutdown(wait=True)
    关闭线程池,不再接收新线程任务,关闭后调用 submit() 和map() 引发 RuntimeError 异常
    wait: 默认True,执行完所有线程后在关闭线程池;False表示立即关闭线程池,但是线程还是可以执行

    Future对象的方法

    Future类封装了一个可调用的异步执行结果对象,Future对象由 submit() 方法创建

    Future.cancel()
    取消当前Future代表的线程任务
    若当前任务正在执行,无法取消,返回 False,否则,该任务被取消并且返回 True
    
    Future.cancelled()
    当前Future代表的线程任务被成功取消返回 True
    
    Future.running()
    当前Future代表的线程任务正在执行,无法取消,返回 Ture
    
    Future.done()
    当前Future代表的线程任务被取消或完成返回 True
    
    Future.result(timeout=None)
    返回当前Future代表的线程任务执行的结果
    timeout: 等待当前Future代表的线程任务执行结果的最大超时时间,int或float类型,默认None,永不超时;若超时,引发 concurrent.futures.TimeoutError 异常
    
    Future.exception(timeout=None)
    返回当前Future代表的线程任务执引发的异常,如没有引发任何异常,返回 False
    timeout: 等待当前Future代表的线程任务执行结果的最大超时时间,int或float类型,默认None,永不超时;若超时,引发 concurrent.futures.TimeoutError 异常
    
    Future.add_done_callback(fn)
    当前Future代表的线程任务被取消或者完成,执行的函数

    示例

    import threading
    from concurrent.futures import ThreadPoolExecutor
    
    #账户类
    class Account:
        def __init__(self, account_no, balance):
            #账户编号和账户余额
            self.account_no = account_no
            self.balance = balance
    
            self._flag = False
            self.cond = threading.Condition()
        
        def getBlance(self):
            return self.balance
        
        #提取现金方法
        def draw(self, draw_amount):
            with self.cond:
                if not self._flag:
                    self.cond.wait()
                else:
                    if self.balance >= draw_amount:
                        print(threading.current_thread().name+'	取钱成功!吐出钞票:'+str(draw_amount))
                        self.balance -= draw_amount
                        print(threading.current_thread().name+'操作之后	余额为:'+str(self.balance))
                    else:
                        print(threading.current_thread().name+'	取钱失败!余额不足!	当前余额为:'+str(self.balance))
                    self._flag = False
                    self.cond.notify_all()
    
        #存钱方法
        def deposit(self, deposit_amount):
            with self.cond:
                if  self._flag:
                    self.cond.wait()
                else:
                    print(threading.current_thread().name+'	存钱成功!存入钞票:'+str(deposit_amount))
                    self.balance += deposit_amount
                    print(threading.current_thread().name+'操作之后	余额为:'+str(self.balance))
                    self._flag = True
                    self.cond.notify_all()
    
    acct = Account('986623', 1000)
    
    with ThreadPoolExecutor(100, thread_name_prefix='Account_Thread_Pool') as pools:
        for i in range(50):
            pools.submit(acct.deposit, 1000)
            pools.submit(acct.draw, 900)
  • 相关阅读:
    【4】通过简化的正则表达式处理字符串
    水晶报表WEB方式下不打印的问题
    字符串处理总结(旧)
    【3】利用Word模板生成文档的总结
    这个教授的观点颇犀利
    互联网时代还需要看书吗?
    怎样更爽地看PDF杂志
    吐槽win7
    信息技术真有想象的那么靠谱吗?
    无线路由器桥接的设置
  • 原文地址:https://www.cnblogs.com/gudanaimei/p/14408848.html
Copyright © 2020-2023  润新知