【python】多线程,定时新增一定数量任务的简单实现
一、需求
希望通过python多线程执行,并且定时向线程池增加任务,直到所有线程任务完成
二、简单demo
import threading import queue import time from typing import Callable class DynamicThreadPool: def __init__( self, max_workers: int, increment_interval: float, increment_count: int ): self.task_queue = queue.Queue() self.max_workers = max_workers self.increment_interval = increment_interval self.increment_count = increment_count self.workers = [] self.scheduler_thread = None self.stop_event = threading.Event() self.lock = threading.Lock() def start(self) -> None: """启动调度线程,开始动态增加工作线程""" self.scheduler_thread = threading.Thread(target=self._scheduler_loop) self.scheduler_thread.start() def _scheduler_loop(self) -> None: """调度器循环,定时增加线程""" while not self.stop_event.is_set(): self._add_workers() time.sleep(self.increment_interval) def _add_workers(self) -> None: """根据增量添加工作线程""" with self.lock: current_workers = len(self.workers) if current_workers >= self.max_workers: return add_num = min( self.increment_count, self.max_workers - current_workers ) for _ in range(add_num): worker = threading.Thread(target=self._worker_loop) worker.daemon = True # 守护线程,主退出时自动终止 worker.start() self.workers.append(worker) def _worker_loop(self) -> None: """工作线程循环,从队列获取任务并执行""" while not self.stop_event.is_set(): try: if not self.task_queue.empty(): # raise Empty error task_func, args, kwargs = self.task_queue.get(timeout=1) task_func(*args, **kwargs) self.task_queue.task_done() except queue.Empty: continue # 超时后重新检查停止事件 except Exception as e: print(f"任务执行失败: {e}") # finally: # ValueError: task_done() called too many times # if not self.task_queue.empty(): def submit(self, func: Callable, *args, **kwargs) -> None: """提交任务到队列""" self.task_queue.put((func, args, kwargs)) def shutdown(self) -> None: """优雅关闭线程池""" self.stop_event.set() # 通知所有线程停止 self.task_queue.join() # 等待队列任务完成 # 等待所有工作线程结束(守护线程会自动退出) with self.lock: for worker in self.workers: if worker.is_alive(): worker.join() if self.scheduler_thread and self.scheduler_thread.is_alive(): self.scheduler_thread.join() # 示例用法 if __name__ == "__main__": def example_task(task_id: int) -> None: print(f"任务 {task_id} 开始,线程ID: {threading.get_ident()}") time.sleep(2) print(f"任务 {task_id} 完成") # 初始化线程池,最大5线程,每3秒增加2个 pool = DynamicThreadPool( max_workers=5, increment_interval=3, increment_count=2 ) pool.start() # 提交10个示例任务 for i in range(10): pool.submit(example_task, i) # 运行10秒后关闭 time.sleep(10) print("准备关闭线程池...") pool.shutdown() print("线程池已关闭")
三、执行结果
任务 0 开始,线程ID: 139256825644736 任务 1 开始,线程ID: 139256815158976 任务 0 完成 任务 2 开始,线程ID: 139256825644736 任务 1 完成 任务 3 开始,线程ID: 139256815158976 任务 4 开始,线程ID: 139256729175744 任务 5 开始,线程ID: 139256718689984 任务 3 完成 任务 6 开始,线程ID: 139256815158976 任务 2 完成 任务 7 开始,线程ID: 139256825644736 任务 4 完成 任务 8 开始,线程ID: 139256729175744 任务 5 完成 任务 9 开始,线程ID: 139256718689984 任务 7 完成 任务 6 完成 任务 8 完成任务 9 完成 准备关闭线程池... 线程池已关闭