python 收录集中实现线程池的方法
概念:
什么是线程池?
诸如web服务器、数据库服务器、文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务。构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就创建一个新的服务对象,然后在新的服务对象中为请求服务。但当有大量请求并发访问时,服务器不断的创建和销毁对象的开销很大。所以提高服务器效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这样就引入了“池”的概念,“池”的概念使得人们可以定制一定量的资源,然后对这些资源进行复用,而不是频繁的创建和销毁。
线程池是预先创建线程的一种技术。线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中。这些线程都是处于睡眠状态,即均为启动,不消耗CPU,而只是占用较小的内存空间。当请求到来之后,缓冲池给这次请求分配一个空闲线程,把请求传入此线程中运行,进行处理。当预先创建的线程都处于运行状态,即预制线程不够,线程池可以自由创建一定数量的新线程,用于处理更多的请求。当系统比较闲的时候,也可以通过移除一部分一直处于停用状态的线程。
1,简易方法,利用队列实现
(1)
from threading import Thread import time, os, queue class Threading_Pool(object): def __init__(self, MAX_NUM = 20): self.queue = queue.Queue(MAX_NUM)
# self.queue.join()
for i in range(MAX_NUM):
self.queue.put(Thread) def get_thread(self):
return self.queue.get() def put_thread(self):
self.queue.put(Thread) def join(self): self.queue.join() def test(tp):
time.sleep(1)
print('haha') tp.put_thread()
# print(tp.queue.full())获取队列是否满了 if __name__ == '__main__':
tp = Threading_Pool(5)
# tp.join()
for i in range(20):
p = tp.get_thread()
t1 = p(target = test, args = (tp, ))
t1.start() 打印结果会1秒出5个
(2)
# -*- coding:utf-8 -*- import Queue
import threading
import time class WorkManager(object):
def __init__(self, work_num=1000,thread_num=2):
self.work_queue = Queue.Queue()
self.threads = []
self.__init_work_queue(work_num)
self.__init_thread_pool(thread_num) """
初始化线程
"""
def __init_thread_pool(self,thread_num):
for i in range(thread_num):
self.threads.append(Work(self.work_queue)) """
初始化工作队列
"""
def __init_work_queue(self, jobs_num):
for i in range(jobs_num):
self.add_job(do_job, i) """
添加一项工作入队
"""
def add_job(self, func, *args):
self.work_queue.put((func, list(args)))#任务入队,Queue内部实现了同步机制 """
等待所有线程运行完毕
"""
def wait_allcomplete(self):
for item in self.threads:
if item.isAlive():item.join() class Work(threading.Thread):
def __init__(self, work_queue):
threading.Thread.__init__(self)
self.work_queue = work_queue
self.start() def run(self):
#死循环,从而让创建的线程在一定条件下关闭退出
while True:
try:
do, args = self.work_queue.get(block=False)#任务异步出队,Queue内部实现了同步机制
do(args)
self.work_queue.task_done()#通知系统任务完成
except:
break #具体要做的任务
def do_job(args):
time.sleep(0.1)#模拟处理时间
print threading.current_thread(), list(args) if __name__ == '__main__':
start = time.time()
work_manager = WorkManager(10000, 10)#或者work_manager = WorkManager(10000, 20)
work_manager.wait_allcomplete()
end = time.time()
print "cost all time: %s" % (end-start) #2次开启不同的线程数运行结果如下:
#work_manager = WorkManager(10000, 10)
cost all time: 100.641790867(单位:秒)
#work_manager = WorkManager(10000, 20)
cost all time:50.5233478546(单位:秒)
2,高效方法(1)
#-*-encoding:utf-8-*-
'''
Created on 2012-3-9
@summary: 线程池
@contact: mailto:zhanglixinseu@gmail.com
@author: zhanglixin
'''
import sys
import threading
import Queue
import traceback # 定义一些Exception,用于自定义异常处理 class NoResultsPending(Exception):
"""All works requests have been processed"""
pass class NoWorkersAvailable(Exception):
"""No worket threads available to process remaining requests."""
pass def _handle_thread_exception(request, exc_info):
"""默认的异常处理函数,只是简单的打印"""
traceback.print_exception(*exc_info) #classes class WorkerThread(threading.Thread):
"""后台线程,真正的工作线程,从请求队列(requestQueue)中获取work,
并将执行后的结果添加到结果队列(resultQueue)"""
def __init__(self,requestQueue,resultQueue,poll_timeout=5,**kwds):
threading.Thread.__init__(self,**kwds)
'''设置为守护进行'''
self.setDaemon(True)
self._requestQueue = requestQueue
self._resultQueue = resultQueue
self._poll_timeout = poll_timeout
'''设置一个flag信号,用来表示该线程是否还被dismiss,默认为false'''
self._dismissed = threading.Event()
self.start() def run(self):
'''每个线程尽可能多的执行work,所以采用loop,
只要线程可用,并且requestQueue有work未完成,则一直loop'''
while True:
if self._dismissed.is_set():
break
try:
'''
Queue.Queue队列设置了线程同步策略,并且可以设置timeout。
一直block,直到requestQueue有值,或者超时
'''
request = self._requestQueue.get(True,self._poll_timeout)
except Queue.Empty:
continue
else:
'''之所以在这里再次判断dimissed,是因为之前的timeout时间里,很有可能,该线程被dismiss掉了'''
if self._dismissed.is_set():
self._requestQueue.put(request)
break
try:
'''执行callable,讲请求和结果以tuple的方式放入requestQueue'''
result = request.callable(*request.args,**request.kwds)
print self.getName()
self._resultQueue.put((request,result))
except:
'''异常处理'''
request.exception = True
self._resultQueue.put((request,sys.exc_info())) def dismiss(self):
'''设置一个标志,表示完成当前work之后,退出'''
self._dismissed.set() class WorkRequest:
'''
@param callable_:,可定制的,执行work的函数
@param args: 列表参数
@param kwds: 字典参数
@param requestID: id
@param callback: 可定制的,处理resultQueue队列元素的函数
@param exc_callback:可定制的,处理异常的函数
'''
def __init__(self,callable_,args=None,kwds=None,requestID=None,
callback=None,exc_callback=_handle_thread_exception):
if requestID == None:
self.requestID = id(self)
else:
try:
self.requestID = hash(requestID)
except TypeError:
raise TypeError("requestId must be hashable")
self.exception = False
self.callback = callback
self.exc_callback = exc_callback
self.callable = callable_
self.args = args or []
self.kwds = kwds or {} def __str__(self):
return "WorkRequest id=%s args=%r kwargs=%r exception=%s" % \
(self.requestID,self.args,self.kwds,self.exception) class ThreadPool:
'''
@param num_workers:初始化的线程数量
@param q_size,resq_size: requestQueue和result队列的初始大小
@param poll_timeout: 设置工作线程WorkerThread的timeout,也就是等待requestQueue的timeout
'''
def __init__(self,num_workers,q_size=0,resq_size=0,poll_timeout=5):
self._requestQueue = Queue.Queue(q_size)
self._resultQueue = Queue.Queue(resq_size)
self.workers = []
self.dismissedWorkers = []
self.workRequests = {} #设置个字典,方便使用
self.createWorkers(num_workers,poll_timeout) def createWorkers(self,num_workers,poll_timeout=5):
'''创建num_workers个WorkThread,默认timeout为5'''
for i in range(num_workers):
self.workers.append(WorkerThread(self._requestQueue,self._resultQueue,poll_timeout=poll_timeout)) def dismissWorkers(self,num_workers,do_join=False):
'''停用num_workers数量的线程,并加入dismiss_list'''
dismiss_list = []
for i in range(min(num_workers,len(self.workers))):
worker = self.workers.pop()
worker.dismiss()
dismiss_list.append(worker)
if do_join :
for worker in dismiss_list:
worker.join()
else:
self.dismissedWorkers.extend(dismiss_list) def joinAllDismissedWorkers(self):
'''join 所有停用的thread'''
#print len(self.dismissedWorkers)
for worker in self.dismissedWorkers:
worker.join()
self.dismissedWorkers = [] def putRequest(self,request ,block=True,timeout=None):
assert isinstance(request,WorkRequest)
assert not getattr(request,'exception',None)
'''当queue满了,也就是容量达到了前面设定的q_size,它将一直阻塞,直到有空余位置,或是timeout'''
self._requestQueue.put(request, block, timeout)
self.workRequests[request.requestID] = request def poll(self,block = False):
while True:
if not self.workRequests:
raise NoResultsPending
elif block and not self.workers:
raise NoWorkersAvailable
try:
'''默认只要resultQueue有值,则取出,否则一直block'''
request , result = self._resultQueue.get(block=block)
if request.exception and request.exc_callback:
request.exc_callback(request,result)
if request.callback and not (request.exception and request.exc_callback):
request.callback(request,result)
del self.workRequests[request.requestID]
except Queue.Empty:
break def wait(self):
while True:
try:
self.poll(True)
except NoResultsPending:
break def workersize(self):
return len(self.workers) def stop(self):
'''join 所有的thread,确保所有的线程都执行完毕'''
self.dismissWorkers(self.workersize(),True)
self.joinAllDismissedWorkers()
测试代码:
#Test a demo if __name__=='__main__':
import random
import time
import datetime
def do_work(data):
time.sleep(random.randint(1,3))
res = str(datetime.datetime.now()) + "" +str(data)
return res def print_result(request,result):
print "---Result from request %s : %r" % (request.requestID,result) main = ThreadPool(3)
for i in range(40):
req = WorkRequest(do_work,args=[i],kwds={},callback=print_result)
main.putRequest(req)
print "work request #%s added." % req.requestID print '-'*20, main.workersize(),'-'*20 counter = 0
while True:
try:
time.sleep(0.5)
main.poll()
if(counter==5):
print "Add 3 more workers threads"
main.createWorkers(3)
print '-'*20, main.workersize(),'-'*20
if(counter==10):
print "dismiss 2 workers threads"
main.dismissWorkers(2)
print '-'*20, main.workersize(),'-'*20
counter+=1
except NoResultsPending:
print "no pending results"
break main.stop()
print "Stop"
高效版(2)(老外所作)
import threading class WorkerTask(object):
"""A task to be performed by the ThreadPool.""" def __init__(self, function, args=(), kwargs={}):
self.function = function
self.args = args
self.kwargs = kwargs def __call__(self):
self.function(*self.args, **self.kwargs) class WorkerThread(threading.Thread):
"""A thread managed by a thread pool.""" def __init__(self, pool):
threading.Thread.__init__(self)
self.setDaemon(True)
self.pool = pool
self.busy = False
self._started = False
self._event = None def work(self):
if self._started is True:
if self._event is not None and not self._event.isSet():
self._event.set()
else:
self._started = True
self.start() def run(self):
while True:
self.busy = True
while len(self.pool._tasks) > 0:
try:
task = self.pool._tasks.pop()
task()
except IndexError:
# Just in case another thread grabbed the task 1st.
pass # Sleep until needed again
self.busy = False
if self._event is None:
self._event = threading.Event()
else:
self._event.clear()
self._event.wait() class ThreadPool(object):
"""Executes queued tasks in the background.""" def __init__(self, max_pool_size=10):
self.max_pool_size = max_pool_size
self._threads = []
self._tasks = [] def _addTask(self, task):
self._tasks.append(task) worker_thread = None
for thread in self._threads:
if thread.busy is False:
worker_thread = thread
break if worker_thread is None and len(self._threads) <= self.max_pool_size:
worker_thread = WorkerThread(self)
self._threads.append(worker_thread) if worker_thread is not None:
worker_thread.work() def addTask(self, function, args=(), kwargs={}):
self._addTask(WorkerTask(function, args, kwargs)) class GlobalThreadPool(object):
"""ThreadPool Singleton class.""" _instance = None def __init__(self):
"""Create singleton instance """ if GlobalThreadPool._instance is None:
# Create and remember instance
GlobalThreadPool._instance = ThreadPool() def __getattr__(self, attr):
""" Delegate get access to implementation """
return getattr(self._instance, attr) def __setattr__(self, attr, val):
""" Delegate set access to implementation """
return setattr(self._instance, attr, val)
python 收录集中实现线程池的方法的更多相关文章
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- python自带的线程池和进程池
#python自带的线程池 from multiprocessing.pool import ThreadPool #注意ThreadPool不在threading模块下 from multiproc ...
- python多进程使用及线程池的使用方法
多进程:主要运行multiprocessing模块 import os,time import sys from multiprocessing import Process class MyProc ...
- python——有一种线程池叫做自己写的线程池
这周的作业是写一个线程池,python的线程一直被称为鸡肋,所以它也没有亲生的线程池,但是竟然被我发现了野生的线程池,简直不能更幸运~~~于是,我开始啃源码,实在是虐心,在啃源码的过程中,我简略的了解 ...
- python(13)线程池:threading
先上代码: pool = threadpool.ThreadPool(10) #建立线程池,控制线程数量为10 reqs = threadpool.makeRequests(get_title, da ...
- Python并发编程之线程池&进程池
引用 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/销毁进程或者线程是非常消耗资源的,这个时候我 ...
- Python并发编程之线程池/进程池--concurrent.futures模块
一.关于concurrent.futures模块 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/ ...
- 使用Java 线程池的利弊及JDK自带六种创建线程池的方法
1. 为什么使用线程池 诸如 Web 服务器.数据库服务器.文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务.请求以某种方式到达服务器,这种方式可能是通过网络协 ...
- 线程池工厂方法newFixedThreadPool()和newCachedThreadPool()
newFixedThreadPool()方法: 该方法返回一个固定数量的线程池,当一个新的任务提交时,线程池中若有空闲线程,则立即执行. 若没有.则新的任务被暂存在一个任务队列中,待线程空闲时,便处理 ...
随机推荐
- mpush 服务器环境配置安装 CentOS 7 and Windows
github-doc https://github.com/mywiki/mpush-doc/blob/master/SUMMARY.md Introduction 1.服务器环境 2.安装Redis ...
- 如何禁止火狐onblur时alert()产生类似选中的拖蓝效果
输入框中onblur 然后alert();会产生 复制 选中的效果的效果( 拖蓝) onblur="aa()"function aa(){ alert("--" ...
- 第十章 MyBatis入门
第十章 MyBatis入门10.1 MyBatis入门 优点:简单且功能强大.能够完全控制SQL语句.容易维护和修改 缺点:移植性不好 使用步骤: 1.下载 ...
- mapTask并行度优化及源码分析
mapTask并行度的决定机制 一个job的map阶段并行度由客户端在提交job时决定,而客户端对map阶段并行度的规划的基本逻辑为:将待处理数据执行逻辑切片(即按照一个特定切片大小,将待处理数据划分 ...
- C#小知识点记录,对象的深拷贝
在CSDN中的定义是: public static string CompareExchange( ref string location1, string value, string compara ...
- 【转】JDBC学习笔记(7)——事务的隔离级别&批量处理
转自:http://www.cnblogs.com/ysw-go/ 数据库事务的隔离级别 对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发 ...
- HubbleDotNet 最新绿色版,服务端免安装,基于eaglet 最后V1.2.8.9版本开发,bug修正,支持一键生成同步表
HubbleDotNet 是一个基于.net framework 的开源免费的全文搜索数据库组件.开源协议是 Apache 2.0.HubbleDotNet提供了基于SQL的全文检索接口,使用者只需会 ...
- centos7安装redis3.0和phpredis扩展详细教程(图文)
整理一下centos7安装redis3.0和phpredis扩展的过程,有需要的朋友可以拿去使用. 一.安装redis3.0 1.安装必要的包 yum install gcc 2.centos7安装r ...
- mac终端ssh连接服务器 空闲的时候 连接断开
ssh_config详解(MAC OSX) 方法1:MAC客户端配置 配置“/etc/ssh/ssh_config”文件 “/etc/ssh/ssh_config” 文件是OpenSSH系统范围的配置 ...
- HTTP协议详解以及URL具体访问过程
1.简介 1.1.HTTP协议是什么? 即超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准.从 ...