Python 线程池的实现

Python 线程池

实现原理

# 将任务放在队列中
#      着手开始处理任务
#         - 创建线程
#                 - 有空闲线程,择不再创建线程
#                 - 不能高于线程池的限制
#                 - 根据任务个数判断
#         - 线程去队列中取任务
import queue
import random
import threading
import time
import contextlib

StopEvent = object()

def thread_pool_callback(status, result):
    if not status:
        logging.error('*** thread pool error *** \n%s %s \n' % (datetime.now(), result))
        
class ThreadPool(object):

    def __init__(self, max_num):
        self.q = queue.Queue()  # 最多创建的线程数(线程池最大容量)
        self.max_num = max_num

        self.terminal = False  # 如果为True 终止所有线程,不在获取新任务
        self.generate_list = []  # 真实创建的线程列表
        self.free_list = []  # 空闲线程数量

    def run(self, func, args, callback=thread_pool_callback):
        """
        线程池执行一个任务
        :param func: 任务函数
        :param args: 任务函数所需参数
        :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数)
        :return: 如果线程池已经终止,则返回True否则None
        """

        if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
            self.generate_thread()  # 创建线程
        w = (func, args, callback,)  # 把参数封装成元祖
        self.q.put(w)  # 添加到任务队列

    def generate_thread(self):
        """
        创建一个线程
        """
        t = threading.Thread(target=self.call)
        t.start()

    def call(self):
        """
        循环去获取任务函数并执行任务函数
        """
        current_thread = threading.currentThread  # 获取当前线程
        self.generate_list.append(current_thread)  # 添加到已经创建的线程里

        event = self.q.get()  # 取任务并执行
        while event != StopEvent:  # 是元组=》是任务;如果不为停止信号  执行任务

            func, arguments, callback = event  # 解开任务包; 分别取出值
            try:
                result = func(*arguments)  # 运行函数,把结果赋值给result
                status = True  # 运行结果是否正常
            except Exception as e:
                status = False  # 表示运行不正常
                # result = e  # 结果为错误信息
                result = traceback.format_exc()

            if callback is not None:  # 是否存在回调函数
                try:
                    callback(status, result)  # 执行回调函数
                except Exception as e:
                    pass

            if self.terminal:  # 默认为False,如果调用terminal方法
                event = StopEvent  # 等于全局变量,表示停止信号
            else:
                # self.free_list.append(current_thread)  #执行完毕任务,添加到闲置列表
                # event = self.q.get()  #获取任务
                # self.free_list.remove(current_thread)  # 获取到任务之后,从闲置列表中删除;不是元组,就不是任务
                with self.worker_state(self.free_list, current_thread):
                    event = self.q.get()

        else:
            self.generate_list.remove(current_thread)  # 如果收到终止信号,就从已经创建的线程列表中删除

    def close(self):  # 终止线程
        num = len(self.generate_list)  # 获取总共创建的线程数
        while num:
            self.q.put(StopEvent)  # 添加停止信号,有多少线程添加多少表示终止的信号
            num -= 1

    def terminate(self):  # 终止线程(清空队列)

        self.terminal = True  # 把默认的False更改成True

        while self.generate_list:  # 如果有已经创建线程存活
            self.q.put(StopEvent)  # 有几个线程就发几个终止信号
        self.q.empty()  # 清空队列

    @contextlib.contextmanager
    def worker_state(self, state_list, worker_thread):
        state_list.append(worker_thread)
        try:
            yield
        finally:
            state_list.remove(worker_thread)

i
def work(i):
    time.sleep(random.randint(1,3))
    print(i)
if __name__=="__main__":
	t1=time.time()
	#不使用线程池
	for item in range(50):
        work(item )
    
    #使用线程池
    pool = ThreadPool(10)
    for item in range(50):
        pool.run(func=work, args=(item,))
    t2=time.time()
    print('耗时',t2-t1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值