python執行緒池進一步認識

pythontab發表於2013-07-26

執行緒池的概念是什麼?

在物件導向程式設計中,建立和銷燬物件是很費時間的,因為建立一個物件要獲取記憶體資源或者其它更多資源。在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頁面來控制執行緒的啟動和停止,而這個執行緒池看起來只是用來併發完任務的。不過我想雖然在控制執行緒方面沒有作用,但是它的併發執行任務的作用還是蠻不錯,或許可以用在爬網頁的部分。


相關文章