from abc import ABCMeta, abstractmethod import logging import time """设计要点:两个核心对象(进行池化的对象、对象池)、三个关键动作对象(借用对象、使用对象、归还对象) 使用注意事项:对已归还的对象的引用,不能在进行任何其他操作,否则将产生不可预料的结果(使用引用计数技术sys.getrefcount()) 应用场景:适用于那些初始化和销毁的代价高且需要经常被实例化的对象,如大对象、需占用I/O的对象 实际应用:线程池、连接池等 """ # 打印INFO以上的信息 logging.basicConfig(level=logging.INFO) class PooledObject: """池对象,池化对象""" def __init__(self, obj): self.__obj = obj self.__busy = obj def getObject(self): return self.__obj def setObject(self, obj): self.__obj = obj def isBusy(self): return self.__busy def setBusy(self, busy): return self.__busy = busy class ObjectPool(metaclass=ABCMeta): """对象池""" """对象池初始化大小""" InitialNumOfObjects = 10 """对象池的大小""" MaxNumOfObjects = 50 def __init__(self): self.__pools = [] for i in range(ObjectPool.InitialNumOfObjects): obj = createPoolObject() self.__pools.append(obj) @abstractmethod def createPoolObject(self): pass def borrowObject(self): """借用独享""" # 如果找到空闲对象,直接返回 obj = self.__findFreeObject() if obj is not None: logging.info("%x对象已被借用,time:%s", id(obj), time.strftime(r"%Y-%m-%d %H:%M:%S", time.localtime(time.time()))) return obj # 如果对象池还未满,则添加新的对象 if(len(self.__pools) < ObjectPool.MaxNumOfObjects): pooledObj = self.addObject() if pooledObj is not None: pooledObj.setBusy(True) logging.info("%x对象已被借用,time:%s", id(obj), time.strftime(r"%Y-%m-%d %H:%M:%S", time.localtime(time.time()))) return pooledObj.getObject() return None def returnObject(self, obj): """归还对象""" for pooledObj in self.__pools: if(pooledObj.getObject() == obj): pooledObj.setBusy(False) logging.info("%x对象已被归还,time:%s", id(obj), time.strftime(r"%Y-%m-%d %H:%M:%S", time.localtime(time.time()))) break def addObj(self): """添加新对象""" obj = None if(len(self.__pools)<ObjectPool.MaxNumOfObjects): obj = self.createPoolObject() self.__pools.append(obj) logging.info("添加新对象%x,time:%s", id(obj), time.strftime(r"%Y-%m-%d %H:%M:%S", time.localtime(time.time()))) return obj def clear(self): """清空对象池""" self.__pools.clear() def __findFreeObject(self): """查找闲置对象""" obj = None for pooledObj in self.__pools: if not pooledObj.isBusy(): obj = pooledObj.getObject() pooledObj.setBusy(True) break return obj