python多线程之线程池基础

本文深入探讨了Python线程池的基本原理与应用,讲解了如何通过预创建线程来提高性能和系统稳定性,避免线程频繁创建与销毁的开销,并提供了一个具体的线程池实现案例。

python线程池问题
线程池基本原理
把任务放进队列中去,然后开N个线程,每个线程都去队列中取一个任务,执行完了之后告诉系统说我执行完了,然后接着去队列中取下一个任务,直至队列中所有任务取空,退出线程
线程池优点
由于线程预先被创建并放入线程池中,同时处理完当前任务之后并不销毁而是被安排处理下一个任务,因此能够避免多次创建线程,从而节省线程创建和销毁的开销,能带来更好的性能和系统稳定性

设置线程池的线程数---限制

  1. 服务器CPU核数有限,能够同时并发的线程数有限
  2. 线程切换是有开销的,如果线程切换过于频繁,会使性能降低

计算原理:

  1. 即计算时间占50%,等待时间50%,那么为了利用率达到最高,可以开2个线程
  2. 如果计算时间占20%, 等待时间80%,那么为了利用率达到最高,可以开5个线程

计算线程数设置的公式----
N核服务器,通过执行业务的单线程分析出本地计算时间为x,等待时间为y,则工作线程数(线程池线程数)设置为 N*(x+y)/x,能让CPU的利用率最大化。
Tips:由于有GIL的影响,python只能使用到1个核,所以这里设置N=1

 

import queue,threading,time
class WorkManager(object):
    def __init__(self,work_num=1000,thread_num=2):
        self.work_queue=queue.Queue
        self.threads=[]
        self.__init_work_queue(work_num)
        self.__init_thread_pool(thread_num)
    #初始化线程
    def __init_thread_pool(self,thread_num):
        for i in range(thread_num):
            self.threads.append(Work(self.work_queue))
    #初始化工作队列
    def __init_work_queue(self,jobs_num):
        for i in range(jobs_num):
            self.add_job(do_job,i)
    #添加一项工作入队
    def add_job(self,func,*args):
        self.work_queue.put((func,list(args)))  #任务入队,Queue内部已经实现了同步机制
    #等待所有线程运行完毕
    def wait_allcomplete(self):
        for item in self.threads:
            if item.isAlive():
                item.join()
class Work(threading.Thread):
    def __init__(self,work_queue):
        threading.Thread.__init__(self)
        self.work_queue=work_queue
        self.start()
    def run(self):
        #死循环,从而让创建的线程在一定条件下关闭退出
        while True:
            try:
                do,args=self.work_queue.get(block=False)###任务异步出队列
                do(args)
                self.work_queue.task_done() #通知系统任务完成
            except:
                break
            #具体要做的任务
def do_job(args):
    time.sleep(0.1)
    print(threading.current_thread())
    print(list(args))

if __name__='__main__':
    start=time.time()
    workManage=WorkManager(100,10) #workManage=WorkManager(10000,20)
    workManage.wait_allcomplete()
    end=time.time()
    print("cost all time: %s"%(end-start))

 

Python 中,可使用 `concurrent.futures` 模块里的 `ThreadPoolExecutor` 来创建线程池,该模块比原 `Thread` 封装程度更高[^3]。关闭线程池可借助 `shutdown` 方法。以下为示例代码: ```python import concurrent.futures import time def task(n): time.sleep(1) return n * n # 创建线程池 with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor: # 提交任务 future_results = [executor.submit(task, i) for i in range(5)] # 获取任务结果 for future in concurrent.futures.as_completed(future_results): print(future.result()) # 当 with 块结束时,线程池会自动调用 shutdown 方法关闭 # executor.shutdown() # 若不使用 with 语句,可手动调用此方法 ``` 在上述代码中,使用了 `with` 语句来管理 `ThreadPoolExecutor` 实例。当 `with` 块结束时,会自动调用 `shutdown` 方法关闭线程池。`shutdown` 方法有两个可选参数: - `wait`:默认为 `True`,表示会等待所有线程完成任务后再关闭线程池;若设为 `False`,则会立即返回,线程池会在后台继续关闭。 - `cancel_futures`:Python 3.9 及以上版本支持,默认为 `False`,若设为 `True`,会尝试取消所有未开始执行的任务。 示例代码如下: ```python import concurrent.futures import time def task(n): time.sleep(1) return n * n executor = concurrent.futures.ThreadPoolExecutor(max_workers=3) future_results = [executor.submit(task, i) for i in range(5)] # 手动关闭线程池,等待所有任务完成 executor.shutdown(wait=True) # 手动关闭线程池,不等待任务完成 # executor.shutdown(wait=False) # Python 3.9 及以上版本,尝试取消未开始的任务 # executor.shutdown(wait=True, cancel_futures=True) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值