線程池的概念是什麼?
在物件導向程式設計中,建立和銷毀物件是很花時間的,因為建立物件要取得記憶體資源或其它更多資源。在Java中更是如此 如此,虛擬機器將試圖追蹤每個對象,以便能夠在對象銷毀後進行垃圾回收。所以提高服務程序效率的一個手段就是盡可能減少創建和銷毀物件的次數,特別是一些 很耗資源的物件創建和銷毀。如何利用已有物件來服務就是一個需要解決的關鍵問題,其實這就是一些"池化資源"技術產生的原因。
我理解為執行緒池是一個存放很多執行緒的單位,同時還有一個對應的任務佇列。整個執行過程其實就是使用執行緒池中已有有限的執行緒把任務 佇列中的任務做完。這樣做的好處就是你不需要為每個任務都創建一個線程,因為當你創建第100個線程來執行第100個任務的時候,可能前面已經有50個線 程結束工作了。因此重複利用執行緒來執行任務,減少系統資源的開銷。
一個不怎麼恰當的比喻就是,有100台電腦主機箱需要從1樓搬到2樓,你不需要喊來100人幫忙搬,你只需要叫十個或二十個人就足以,每個人分配十個或五個甚至是誰搬的快誰就多搬知道完成未知。 (這個比喻好像。。。。。)
不管如何吧,大體上理解了線程池的概念。那要怎麼用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分配製定的任務量和執行緒數,然後每個執行緒都從任務佇列中取得任務來執行,直到佇列中沒有任務。這裡面也用到了Queue內部的同步機制(至於是啥同步機制目前還沒去研究)。
總結一下這樣一個線程池的作用,對於我本來的目的其實這個東西是永不上的,因為我需要在web頁面來控制線程的啟動和停止,而這個線程池看起來只是用來並發完任務的。不過我想雖然在控制線程方面沒有作用,但是它的並發執行任務的作用還蠻不錯,或許可以用在爬網頁的部分。