目的: 我们想去创建一个工作者线程池来处理客户端的连接,让每个线程去处理各自的客户,或者完成其他类型的工作。 方法: 在concurrent。futures库中包含了ThreadPoolExecutor类可以实现这个目的。下面的例子是一个简单TCP服务器,使用线程池来处理客户端:fromsocketimportAFINET,SOCKSTREAM,socketfromconcurrent。futuresimportThreadPoolExecutordefechoclient(sock,clientaddr):print(Gotconnectionfrom:,clientaddr)whileTrue:msgsock。recv(65536)ifnotmsg:breaksock。sendall(msg)print(sock,hasbeensentallmessage。。。)sock。close()defechoserver(addr):poolThreadPoolExecutor(128)socksocket(AFINET,SOCKSTREAM)sock。bind(addr)sock。listen()whileTrue:clientsock,clientaddrsock。accept()服务器接收客户端请求pool。submit(echoclient,clientsock,clientaddr)提交给线程池中的处理函数去处理客户端echoserver((localhost,21000))服务器启动 同样,可以抛开concurrent。futures中的ThreadPoolExecutor,直接手动创建线程池,如果借助Queue则会变得容易:fromsocketimportSOCKSTREAM,AFINET,socketfromthreadingimportThreadfromqueueimportQueuedefechoclient(q):sock,clientaddrq。get()print(gotconnection:,clientaddr)whileTrue:msgsock。recv(65536)ifnotmsg:breaksock。sendall(msg)print(clientclose)sock。close()defechoserver(addr,clientcount):qQueue()forxinrange(clientcount):tThread(targetechoclient,args(q,),daemonTrue)t。start()socksocket(SOCKSTREAM,AFINET)sock。bind(addr)sock。listen(5)whileTrue:sock,clientaddrsock。accept()q。put(sock,clientaddr) 当然又有一句很蹩脚的话,不建议各位这样使用!!应该去使用concurrent。futures中的ThreadPoolExecutor,这么做的优势在于提交任务者可以很好地拿到处理后的结果:fromconcurrent。futuresimportThreadPoolExecutorimporturllib。requestdefrequesturl(url):uurllib。request。urlopen(url)datau。read()returndatapoolThreadPoolExecutor(10)apool。submit(requesturl,rhttp:www。xxxxxx。com)bpool。submit(requesturl,rhttp:www。xxxxxx。org)res1a。result()会阻塞等待上述中a取出结果后再解除阻塞res2b。result() 讨论一个大家都很容易想到的问题,有些人认为,应该在服务器接收到一个客户端连接时就去开辟一个线程来处理这个客户端的事务,本质上来讲这样确实没有问题,但是,万一一个黑客用大量的客户端去访问服务时,有可能会因为开辟太多线程导致服务器挂掉,这是初学者都会想到的思路,但是,一旦涉及多并发程序,切记一定要限制线程个数,为了系统稳定和安全。下面为各位展示初学者的代码:fromthreadingimportThreadfromsocketimportsocket,AFINET,SOCKSTREAMdefechoclient(sock,clientaddr):print(GOTaconnection:,clientaddr)whileTrue:msgsock。recv(65536)ifnotmsg:breaksock。sendall(msg)sock。close()defechoserver(addr:tuple):socksocket(AFINET,SOCKSTREAM)sock。bind(addr)sock。listen(5)whileTrue:clientsock,clientaddrsock。accept()tThread(targetechoclient,args(clientsock,clientaddr))t。daemonTruet。start()echoserver((localhost,21000)) 这里也要注意,线程只适合做IO密集型的任务。综上关于线程池的内容就介绍到这里