python实现自定义线程池

线程池ThreadPool对象的几个关键方法:

  • get_idle_num(): 获得当前空闲线程的数量
  • submit(task:callable): 把一个任务(实际上就是一个函数)提交到线程池中执行. 如果没有空闲线程则阻塞.
  • wait_idle(): 阻塞, 直到有空闲线程
  • stop(): 停止线程池中的所有线程. (注意: 非强制停止, 需要现有任务执行完毕.)

源码如下:

import queue
import threading
import time

class ThreadPool:
    '''线程池'''
    def __init__(self) -> None:
        self.threads_num = 3
        '''线程的数量'''
        self.idle_count = self.threads_num
        '''空闲线程的数量'''
        self._lock = threading.Lock()
        '''线程锁'''
        self._semaphore = threading.Semaphore(self.threads_num)
        '''信号量, 用于控制线程是否空闲'''
        self.task_queue = queue.Queue()
        '''任务队列'''
        self.threads:list[threading.Thread] = []
        '''线程列表'''
        self._start()
    def get_idle_num(self)->int:
        '''获取空闲线程的数量'''
        return self.idle_count
    def join(self):
        '''等待所有线程执行完毕'''
        for thread in self.threads:thread.join()
    def _start(self):
        '''启动线程池'''
        for _ in range(self.threads_num):
            thread = threading.Thread(target=self._worker, daemon=True)  # 创建线程
            thread.start()
            self.threads.append(thread)
    def stop(self):
        '''停止线程池'''
        # 通过向任务队列中添加None,来终止线程
        for _ in range(self.threads_num): self.task_queue.put(None)
    def submit(self, task:callable):
        '''提交任务到线程池. 如果没有空闲线程, 则会阻塞'''
        self._semaphore.acquire()  # 等待有线程空闲
        self.task_queue.put(task)
    def wait_idle(self):
        '''等待有线程空闲'''
        # 通过信号量控制,当空闲线程数量为0时,信号量会阻塞
        with self._semaphore: pass
    def _worker(self):
        '''线程工作函数'''
        while True:
            task = self.task_queue.get()  # 从队列中取出一个任务执行
            if task is None: 
                self._semaphore.release()  # 释放信号量,通知其他线程
                break  # 用于终止线程的方式
            # 空闲的线程数量减1
            with self._lock: self.idle_count -= 1
            task()  # 执行任务
            # 任务执行完毕,空闲的线程数量加1
            with self._lock: self.idle_count += 1
            #self.task_queue.task_done()  # 通知任务队列,任务完成
            self._semaphore.release()  # 释放信号量,通知其他线程
            
if __name__ == '__main__':
    '''测试线程池'''
    pool = ThreadPool()
    pool.wait_idle()
    print('ok')
    pool.submit(lambda: time.sleep(10))
    pool.submit(lambda: time.sleep(15))
    pool.submit(lambda: time.sleep(20))
    #time.sleep(0.001)
    pool.wait_idle()
    print('ok1')
    print(pool.get_idle_num())
    pool.stop()
    pool.join()
    print('ok2')
posted @ 2024-06-10 11:32  顺其自然,道法自然  阅读(19)  评论(0编辑  收藏  举报