您的位置:首页 > 编程语言 > Python开发

Python线程池简单实现

2015-02-09 13:33 155 查看

Python线程池简单实现

线程池介绍

IBM文档:线程池的介绍及简单实现

这些都是假设,不能充分说明问题,下面我将讨论线程池的简单实现并对该程序进行对比测试,以说明线程技术优点及应用领域。

假设过后一定要验证,单纯开脑洞没有意义…

简单地说,“池化资源”技术就是用空间换时间,事先分配好资源,用的时候直接用,程序结束时释放资源,这样在使用资源时便可省去分配和释放的时间,最终实现性能的提升。

tips:

这种“事先分配N个资源,供之后M次调用”的方案,除提升性能外,还有以下好处:

1、N < M时,可实现复用,避免资源消耗过大。比如在一个socket上模拟多个socket通信,真实socket实现包的分发。这样可以避免多socket通信带来过大的资源消耗。

2、N > M时,可实现冗余。

3、将资源分配与资源使用解耦。

文档中给出的线程池架构如下:

一般一个简单线程池至少包含下列组成部分。

线程池管理器(ThreadPoolManager):用于创建并管理线程池

工作线程(WorkThread): 线程池中线程

任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。

任务队列:用于存放没有处理的任务。提供一种缓冲机制。

线程池管理器至少有下列功能:创建线程池,销毁线程池,添加新任务



上图为一个最原始的线程池架构图。用户使用线程池管理器提供的接口添加任务。线程池管理线程和工作线程使用任务队列传递任务信息(调用的函数、参数)。

类似于C中的main函数,在调用main函数前需要做一些初始化工作,对应的,main函数结束后需要做一些清理工作。C的做法是先调用CRTStartup系列函数,在该函数中调用main函数。工作线程执行任务时可使用类似的做法,与CRTStartup系列函数对应的便是任务接口。最简单的任务接口,只需要不断查询任务队列即可。

Python实现

以下是用Python简单实现的线程池

import threading
import queue

class Work_Thread(threading.Thread):
"""工作线程类
"""
def __init__(self, work_queue):
"""工作线程类初始化函数
"""
threading.Thread.__init__(self)
self._work_queue = work_queue #线程同步队列
self.setDaemon(True) #主线程退出后,子线程也退出
self.start()

def run(self):
"""任务接口
"""
while True:
try:
func, args = self._work_queue.get()
func(args)
self._work_queue.task_done()
except Exception as reason:
print(reason)
break

class Thread_Pool(object):
"""线程池管理类
"""
def __init__(self, thread_count = 1):
"""线程池管理器初始化函数

Args:
thread_count: 线程池中的线程个数
"""
self._thread_count = thread_count
self._work_queue = queue.Queue()
self._threads = []
self.init_threads_pool()

def init_threads_pool(self):
"""建立并启动thread_count个线程
"""
for index in range(self._thread_count):
self._threads.append(Work_Thread(self._work_queue))

def add_work(self, function, param):
"""增加新任务。 (调用函数,参数)
"""
self._work_queue.put((function, param))

def wait_queue_empty(self):
"""等待队列为空。某些场景下可等同于所有任务均执行完
"""
self._work_queue.join()

def work_func(num):
"""测试函数,在控制台打印num
"""
print(num)

def main():
"""Thread_Pool使用例子
"""
thread_count = 5
thread_pool = Thread_Pool(thread_count)
for num in range(0, 100):
thread_pool.add_work(work_func, num) #添加任务
thread_pool.wait_queue_empty() #等待任务执行完

print("---end---")

if __name__ == "__main__":
main()


Tips

除了提升性能,线程池可以减少启动线程的代码。

以Python为例,启动线程需要创建线程对象并调用
start()
方法。若使用线程池,则只需调用
add_work()
方法。

欢迎讨论:)如有错误还望留言指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: