【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 完成

准备关闭线程池...
线程池已关闭

 

posted @ 2025-04-29 16:25  代码诠释的世界  阅读(56)  评论(0)    收藏  举报