python(13)多線程:線程池,threading

 python 多進程:多進程html

先上代碼:python

 

 1 pool = threadpool.ThreadPool(10) #創建線程池,控制線程數量爲10 
 2 reqs = threadpool.makeRequests(get_title, data, print_result) #構建請求,get_title爲要運行的函數,data爲要多線程執行函數的參數
 3                                                               #最後這個print_result是可選的,是對前兩個函數運行結果的操做 
 4 [pool.putRequest(req) for req in reqs] #多線程一塊執行 
 5 pool.wait() #線程掛起,直到結束

 

1 [pool.putRequest(req) for req in reqs] #至關於以下兩行代碼
2 for req in requests:  
3   pool.putRequest(req)  

示例代碼web

 1 import threadpool 
 2 import time,random 
 3 import Queue
 4 
 5 def hello1(str): 
 6     time.sleep(2) 
 7     return str 
 8 
 9 def print_ret(request, result): 
10     print "the result is %s %r\n" % (request.requestID, result) 
11 
12 
13 def deal_task(pool):
14     try:
15         pool.poll(True)
16     except Exception, e:
17         print str(e)
18 
19 #lst = [1,2,3,4,5,6,7]
20 q = Queue.Queue()
21 for i in range(100):
22     q.put(i)
23 
24 lst = [q.get() for i in range(q.qsize())]
25 
26 pool = threadpool.ThreadPool(20) 
27 requests = threadpool.makeRequests(hello1, lst, print_ret) 
28 for req in requests:
29     pool.putRequest(req)
30     #deal_task(pool)
31 
32 pool.wait()

 

 

什麼是線程池?算法

諸如web服務器、數據庫服務器、文件服務器和郵件服務器等許多服務器應用都面向處理來自某些遠程來源的大量短小的任務。構建服務器應用程序的一個過於簡 單的模型是:每當一個請求到達就建立一個新的服務對象,而後在新的服務對象中爲請求服務。但當有大量請求併發訪問時,服務器不斷的建立和銷燬對象的開銷很 大。因此提升服務器效率的一個手段就是儘量減小建立和銷燬對象的次數,特別是一些很耗資源的對象建立和銷燬,這樣就引入了「池」的概念,「池」的概念使 得人們能夠定製必定量的資源,而後對這些資源進行復用,而不是頻繁的建立和銷燬。數據庫

線程池是預先建立線程的一種技術。線程池在尚未任務到來以前,建立必定數量的線程,放入空閒隊列中。這些線程都是處於睡眠狀態,即均爲啓動,不消耗 CPU,而只是佔用較小的內存空間。當請求到來以後,緩衝池給此次請求分配一個空閒線程,把請求傳入此線程中運行,進行處理。當預先建立的線程都處於運行 狀態,即預製線程不夠,線程池能夠自由建立必定數量的新線程,用於處理更多的請求。當系統比較閒的時候,也能夠經過移除一部分一直處於停用狀態的線程。服務器

線程池的注意事項多線程

雖然線程池是構建多線程應用程序的強大機制,但使用它並非沒有風險的。在使用線程池時需注意線程池大小與性能的關係,注意併發風險、死鎖、資源不足和線程泄漏等問題。併發

(1)線程池大小。多線程應用並不是線程越多越好,須要根據系統運行的軟硬件環境以及應用自己的特色決定線程池的大小。通常來講,若是代碼結構合理的話,線程數目與CPU 數量相適合便可。若是線程運行時可能出現阻塞現象,可相應增長池的大小;若有必要可採用自適應算法來動態調整線程池的大小,以提升CPU 的有效利用率和系統的總體性能。dom

(2)併發錯誤。多線程應用要特別注意併發錯誤,要從邏輯上保證程序的正確性,注意避免死鎖現象的發生。函數

(3)線程泄漏。這是線程池應用中一個嚴重的問題,當任務執行完畢而線程沒能返回池中就會發生線程泄漏現象。

簡單線程池的設計

一個典型的線程池,應該包括以下幾個部分:
一、線程池管理器(ThreadPool),用於啓動、停用,管理線程池
二、工做線程(WorkThread),線程池中的線程
三、請求接口(WorkRequest),建立請求對象,以供工做線程調度任務的執行
四、請求隊列(RequestQueue),用於存放和提取請求
五、結果隊列(ResultQueue),用於存儲請求執行後返回的結果

線程池管理器,經過添加請求的方法(putRequest)向請求隊列(RequestQueue)添加請求,這些請求事先須要實現請求接口,即傳遞工做 函數、參數、結果處理函數、以及異常處理函數。以後初始化必定數量的工做線程,這些線程經過輪詢的方式不斷查看請求隊列(RequestQueue),只 要有請求存在,則會提取出請求,進行執行。而後,線程池管理器調用方法(poll)查看結果隊列(resultQueue)是否有值,若是有值,則取出, 調用結果處理函數執行。經過以上講述,不難發現,這個系統的核心資源在於請求隊列和結果隊列,工做線程經過輪詢requestQueue得到人物,主線程 經過查看結果隊列,得到執行結果。所以,對這個隊列的設計,要實現線程同步,以及必定阻塞和超時機制的設計,以防止由於不斷輪詢而致使的過多cpu開銷。

線程池實現原理圖

 

相關文章
相關標籤/搜索