PYTHON__Thread達到上限的解決方案(設置線程上限)


Can't start new thread解決方案(設置線程上限)

背景:

在編寫一個爬蟲的時候,檢查用多線程來檢測結果有效性的時候,線程啟動過多報錯:

thread.error: can't start new thread

方案:使用Thread中的event,並進行上鎖設置來解決。

原因:這個是由於每台計算機能進行的並行是有上限的,經過測試本機的上限為1023個左右(win7 64位,i3 2核4線程),可以進行設置提高上限,但我覺得此處沒有必要,也不方便擴展,所以想自行定義一個並行的上限數進行處理。

參考:在多次百度無果之后,選擇了google,查看了國外的一些評論和解決方案,在google學術中搜索“python thread number limit”,下載了此篇pdf,13-14頁中找到了解決方案,果然是老外做的東西,老外更懂啊。

http://python-ray.googlecode.com/hg-history/425d613ba8a2c7bd367b573018df45e5ec474428/doc/PyThreads.pdf

解決方案:

具體解決方案如下,對應的代碼加上了注釋。

 1 #coding=utf-8
 2 import threading
 3 
 4 class scanner(threading.Thread):
 5     tlist=[] #用來存儲隊列的線程
 6     maxthreads=100 # int(sys.argv[2])最大的並發數量,此處我設置為100,測試下系統最大支持1000多個
 7     evnt=threading.Event()#用事件來讓超過最大線程設置的並發程序等待
 8     lck=threading.Lock() #線程鎖
 9     def __init__(self):
10         threading.Thread.__init__(self)
11     def run(self):
12         try:
13             pass
14         except Exception,e:
15             print e.message
16         #以下用來將完成的線程移除線程隊列
17         scanner.lck.acquire()
18         scanner.tlist.remove(self)
19         #如果移除此完成的隊列線程數剛好達到99,則說明有線程在等待執行,那么我們釋放event,讓等待事件執行
20         if len(scanner.tlist)==scanner.maxthreads-1:
21             scanner.evnt.set()
22             scanner.evnt.clear()
23         scanner.lck.release()
24     def newthread(proxy,counter):
25         scanner.lck.acquire()#上鎖
26         sc=scanner()
27         scanner.tlist.append(sc)
28         scanner.lck.release()#解鎖
29         sc.start()
30     #將新線程方法定義為靜態變量,供調用
31     newthread=staticmethod(newthread)
32 
33 def runscan():
34     for i in 1 .. 100:
35         scanner.lck.acquire()
36         #如果目前線程隊列超過了設定的上線則等待。
37         if len(scanner.tlist)>=scanner.maxthreads:
38             scanner.lck.release()
39             scanner.evnt.wait()#scanner.evnt.set()遇到set事件則等待結束
40         else:
41             scanner.lck.release()
42         scanner.newthread(proxy,counter)
43         
44     for t in scanner.tlist:
45         t.join()#join的操作使得后面的程序等待線程的執行完成才繼續
46 
47 if __name__=="__main__":
48     runscan()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM