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开销。

线程池实现原理图

 

相关文章
相关标签/搜索