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()