设计模式
单例模式
简单来说就是一个类只允许生成一个实例化对象,就是无论用户创建多少次对象,所实例化的对象有且只有一个。
- 懒汉式
通过 obj = 类.方法() 方式来实例化对象
import threading
import time
class Singleton:
_count = 0
lock = threading.RLock()
def __init__(self,*args, **kwargs):
time.sleep(0.2)
@classmethod
def instance(cls,*args, **kwargs):
if not hasattr(Singleton, '_instance'): # 先一步进行筛选,用于减少线程锁的消耗,
with cls.lock: # 利用上下文方式调用锁
if not hasattr(Singleton, '_instance'):
# 虽然觉得多余,但由于线程锁的关系,一旦其他线程执行快的话,会堵在锁的位置。如果缺少了这一句代码的话,一旦第一个实例对象创建完成,释放锁,再进入一个线程,依然还会再创建新的实例对象。 ‘自己练习时可以去掉这一句试试’
cls._instance = Singleton() # 实例化对象
cls._count += 1 # 用于验证对象的创建,实践中可去除
return cls._instance
def get_count(self):
return self._count
def run():
obj = Singleton().instance()
print('{}\t{}'.format(obj, obj.get_count()))
if __name__ == '__main__':
for _ in range(3):
t = threading.Thread(target=run)
t.start()
- 饿汉式
通过 obj = 类() 方式直接生成实例化对象
import time
import threading
class Singleton:
_count = 0
lock = threading.RLock() # 实例化线程锁对象
def __init__(self):
time.sleep(0.2)
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, '_instance'): # 减少线程锁资源消耗,存在不用进入线程锁
cls._instance = object.__new__(cls)
cls._count += 1
return Singleton._instance
def get_count(self):
return self._count
def run():
obj = Singleton()
print('{}\t{}'.format(obj, obj.get_count()))
if __name__ == '__main__':
for _ in range(10):
t = threading.Thread(target=run)
t.start()
-
分析:
饿汉式实例化类时会创建一个单例的实例化对象,但不管现在是否需要这个单例对象它都会创建,在一定程度上节省了创建时间,但要占用资源。懒汉式在需要用到这个单例对象时,通过相应的类方法进行创建,相对节省资源,但进程不安全,要保证进程安全需要加锁,操作相对麻烦。
饿汉式采用的是空间换时间,懒汉式采用的是时间换空间,相对来说推荐饿汉式,更加安全方便。