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