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

 

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