线程池的概念是什么?
在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是 如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些 很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因。
我理解为线程池是一个存放很多线程的单位,同时还有一个对应的任务队列。整个执行过程其实就是使用线程池中已有有限的线程把任务 队列中的任务做完。这样做的好处就是你不需要为每个任务都创建一个线程,因为当你创建第100个线程来执行第100个任务的时候,可能前面已经有50个线 程结束工作了。因此重复利用线程来执行任务,减少系统资源的开销。
一个不怎么恰当的比喻就是,有100台电脑主机箱需要从1楼搬到2楼,你不需要喊来100人帮忙搬,你只需要叫十个或者二十个人就足以,每个人分配十个或者五个甚至是谁搬的快谁就多搬知道完成未知。(这个比喻好像。。。。。)
不管如何吧,大体上理解了线程池的概念。那么怎么用python实现呢?
代码如下
#!/usr/bin/envpython #-*-coding:utf-8-*- #ref_blog:http://www.open-open.com/home/space-5679-do-blog-id-3247.html importQueue importthreading importtime classWorkManager(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): foriinrange(thread_num): self.threads.append(Work(self.work_queue)) """ 初始化工作队列 """ def__init_work_queue(self,jobs_num): foriinrange(jobs_num): self.add_job(do_job,i) """ 添加一项工作入队 """ defadd_job(self,func,*args): self.work_queue.put((func,list(args)))#任务入队,Queue内部实现了同步机制 """ 检查剩余队列任务 """ defcheck_queue(self): returnself.work_queue.qsize() """ 等待所有线程运行完毕 """ defwait_allcomplete(self): foriteminself.threads: ifitem.isAlive():item.join() classWork(threading.Thread): def__init__(self,work_queue): threading.Thread.__init__(self) self.work_queue=work_queue self.start() defrun(self): #死循环,从而让创建的线程在一定条件下关闭退出 whileTrue: try: do,args=self.work_queue.get(block=False)#任务异步出队,Queue内部实现了同步机制 do(args) self.work_queue.task_done()#通知系统任务完成 exceptException,e: printstr(e) break #具体要做的任务 defdo_job(args): printargs time.sleep(0.1)#模拟处理时间 printthreading.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"costalltime:%s"%(end-start)
这个代码清晰易懂。
整个代码只有两个类:WorkManager和Work,前者确实如命名所示,是一个管理者,管理线程池和任务队列,而后者就是具体的一个线程。
它的整个运行逻辑就是,给WorkManager分配制定的任务量和线程数,然后每个线程都从任务队列中获取任务来执行,直到队列中没有任务。这里面也用到了Queue内部的同步机制(至于是啥同步机制目前还没去研究)。