Python实现简易线程池:原理与代码解析
本文解析Python中线程池的基本概念与实现原理。通过WorkManager和Work两个核心类,利用Queue模块的任务队列与同步机制,实现有限线程复用以执行并发任务。文章包含完整代码示例,分析线程初始化、任务入队及执行流程,并探讨其在爬虫等场景下的应用价值。
线程池的核心概念是什么?
在面向对象编程中,对象的创建与销毁往往消耗大量时间,因为需要分配内存或其他资源。以Java为例,虚拟机需跟踪每个对象以便进行垃圾回收,因此降低服务程序开销的关键在于减少对象的创建与销毁频率,尤其是那些资源密集型对象。如何复用现有对象来提供服务,成为“池化资源”技术诞生的根本原因。
直观理解,线程池是一个存储多个线程的容器,并配有一个对应的任务队列。其执行逻辑是利用池中有限的线程,依次处理任务队列中的任务。这样做的好处在于无需为每个任务单独创建新线程;例如,当第100个任务启动时,前50个任务的线程可能已空闲,从而通过复用线程显著降低系统资源开销。
用一个不太严谨的比喻:若有100台电脑主机箱需要从一楼搬运至二楼,无需雇佣100人,只需召集10至20人即可。分配每人搬运10台或5台,甚至谁搬得快谁多搬,直到任务完成。(尽管该比喻略显牵强,但旨在说明资源复用与负载均衡的思想。)
在理解线程池基本概念后,接下来探讨如何使用Python实现这一机制。
具体实现代码如下:
# !/usr/bin/env python
# -*- coding:utf-8 -*-
# ref_blog:http://www.open-open.com/home/space-5679-do-blog-id-3247.html
import Queue
import threading
import time
class WorkManager(object):
def __init__(self, work_num=1000,thread_num=2):
self.work_queue = Queue.Queue()
self.threads = []
self.__init_work_queue(work_num)
self.__init_thread_pool(thread_num)
"""
初始化线程
"""
def __init_thread_pool(self,thread_num):
for i in range(thread_num):
self.threads.append(Work(self.work_queue))
"""
初始化工作队列
"""
def __init_work_queue(self, jobs_num):
for i in range(jobs_num):
self.add_job(do_job, i)
"""
添加一项工作入队
"""
def add_job(self, func, *args):
self.work_queue.put((func, list(args)))#任务入队,Queue内部实现了同步机制
"""
检查剩余队列任务
"""
def check_queue(self):
return self.work_queue.qsize()
"""
等待所有线程运行完毕
"""
def wait_allcomplete(self):
for item in self.threads:
if item.isAlive():item.join()
class Work(threading.Thread):
def __init__(self, work_queue):
threading.Thread.__init__(self)
self.work_queue = work_queue
self.start()
def run(self):
#死循环,从而让创建的线程在一定条件下关闭退出
while True:
try:
do, args = self.work_queue.get(block=False)#任务异步出队,Queue内部实现了同步机制
do(args)
self.work_queue.task_done()#通知系统任务完成
except Exception,e:
print str(e)
break
#具体要做的任务
def do_job(args):
print args
time.sleep(0.1)#模拟处理时间
print threading.current_thread(), list(args)
if __name__ == '__main__':
start = time.time()
work_manager = WorkManager(10, 2)#或者work_manager = WorkManager(10000, 20)
work_manager.wait_allcomplete()
end = time.time()
print "cost all time: %s" % (end-start)
该代码结构清晰,易于理解。
整个实现仅包含两个类:WorkManager和Work。正如命名所示,WorkManager负责管理线程池和任务队列,而Work则代表具体的工作线程。
其运行逻辑为:向WorkManager指定任务总量和线程数量,随后每个线程从任务队列中获取任务并执行,直至队列为空。此过程利用了Queue模块内部的同步机制(具体同步细节待进一步研究)。
总结而言,该线程池的主要作用在于并发执行任务。虽然它无法直接满足Web页面控制线程启停的需求,但其高效的并发处理能力仍颇具价值,例如可应用于网页爬虫场景中。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













