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))

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章