单例模式是一种常见的软件设计模式。主要是确保一个类只有一个实例存在。单例模式可以节约系统资源。
class Animal(object): instance = None @staticmethod def __new__(cls, *args, **kwargs): if not cls.instance: cls.instance = super(Animal, cls).__new__(cls) return cls.instance dog = Animal() cat = Animal() print(id(dog)) print(id(cat))
def singleton(cls): """单例模式装饰器""" instance = {} def get_instance(): if cls not in instance: instance[cls] = cls() return instance[cls] return get_instance @singleton class Animal(object): def __init__(self): pass
class Animal(type): """使用元类实现单例模式""" instance = None def __call__(cls): if not cls.instance: cls.instance = super(Animal, cls).__call__() return cls.instance class Dog(metaclass=Animal): pass
创建一个类的实例,然后在其他文件里import进去。
class Animal(object): """使用元类实现单例模式""" def __init__(self): pass @staticmethod def get_instance(): if not hasattr(Animal, "_instance"): Animal._instance = Animal() return Animal._instance def create_singleton(): small_animal = Animal.get_instance() print(id(small_animal)) create_singleton() create_singleton()
注:这样的单例模式在单线程下是安全的,但是如果遇到多线程,就会出现问题。示例代码如下:
import time from concurrent.futures import ThreadPoolExecutor class Animal(object): """使用元类实现单例模式""" def __init__(self): time.sleep(1) pass @staticmethod def get_instance(): if not hasattr(Animal, "_instance"): Animal._instance = Animal() return Animal._instance def create_singleton(): small_animal = Animal.get_instance() print(id(small_animal)) if __name__ == "__main__": with ThreadPoolExecutor(max_workers=10) as executor: for i in range(10): executor.submit(create_singleton)
运行结果如下图所示,创建了10个实例。
解决:加锁。在在获取对象属性_instance的时候加锁,加锁后的代码如下:
import time from concurrent.futures import ThreadPoolExecutor import threading class Animal(object): """使用元类实现单例模式""" _lock = threading.Lock() def __init__(self): time.sleep(1) @staticmethod def get_instance(): if not hasattr(Animal, "_instance"): with Animal._lock: if not hasattr(Animal, ‘_instance‘): Animal._instance = Animal() return Animal._instance def create_singleton(): small_animal = Animal.get_instance() print(id(small_animal)) if __name__ == "__main__": with ThreadPoolExecutor(max_workers=10) as executor: for i in range(10): executor.submit(create_singleton)
原文:https://www.cnblogs.com/theshy1103/p/13127466.html