
#!/ufr/bin/env python # -*- coding:utf-8 -*- import xlwings as xw import queue import threading import time StopEvent = object() class TreadPool: def __init__(self, max_num, max_tast_num = 0): self.max_num = max_num #最大線程數 if max_tast_num: #根據是否制定最大任務數來指定隊列程度 self.q = queue.Queue() #隊列不限定長度 else: self.q = queue.Queue(max_tast_num) #根據用戶指定長度創建隊列 self.generate_list = [] #記錄生成的線程 self.free_list = [] #記錄空閑的線程 self.terminal = False def run(self, target, args, callback=None): """運行該函數,調用線程池""" if len(self.free_list) == 0 and len(self.generate_list) < self.max_num: #沒有空閑線程並且當前創建線程數量小於最大允許線程數量時允許創建線程 self.creat_thread() #調用創建線程函數 tast = (target, args, callback) #將任務打包成為元組放入隊列 self.q.put(tast) def creat_thread(self): """創建線程,並且運行,這時調用call函數,所有實現均在call函數內""" thread = threading.Thread(target=self.call) thread.start() def call(self): """線程調用該函數""" current_thread = threading.currentThread() #獲取執行該函數的當前線程 self.generate_list.append(current_thread) #將線程加入生成的線程列表 tast = self.q.get() #從隊列中取出一個任務包 while tast != StopEvent: target, args, backcall = tast #將元組人物包,賦值給變量 try: result = target(*args) #執行函數,並將返回值賦值給result except Exception as e: result = None if backcall: try: backcall(result) #執行回調函數,並將result作為參數傳給回調函數 except Exception as e: pass self.free_list.append(current_thread) #執行完畢,將當前線程對象加入空閑列表 if self.terminal: #是否強制終止 tast = StopEvent else: tast = self.q.get() #等待那任務,如果有任務直接循環執行,如果沒有則等待,一旦run方法中放入任務則繼續執行任務,無需再創建線程 self.free_list.remove(current_thread) #拿到任務后,清除空閑線程 else: self.generate_list.remove(current_thread) def close(self): """所有線程全部運行完畢后,停止線程 call函數運行完畢后,所有的線程此時都在等待拿任務,此時,只要給隊列里面添加StopEvent對象則線程就會結束""" generate_size = len(self.generate_list) while generate_size: self.q.put(StopEvent) generate_size -= 1 def terminate(self): """不等待線程全部運行完畢任務,直接終止""" self.terminal = True #正在運行的線程運行完畢后會終止 generate_size = len(self.generate_list) while generate_size: #終止已經在等待的那一部分線程 self.q.put(StopEvent) generate_size -= 1 def func(li): for i in range(10000): li.append([i]) def world(): wb = xw.Book.caller() li = [] pool = TreadPool(5) for i in range(5): pool.run(target=func, args=(li,)) pool.close() print(li) wb = xw.Book.caller() wb.sheets[0].range("a1").value = li