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