在python下,在多线程下使用单例模式的情况比较多.这里就列出两种我觉得比较好的实现:
第一种是装饰类来实现:
from concurrent.futures import ThreadPoolExecutor
def singleton (cls, *args, **kwargs):
"""
线程安全单例装饰器.
如果需要继承单例,装饰器可以绑定到子类上实现.父类不要绑定.
Args:
cls (class): 单例类名
*args : 单例的初始化参数
**kwargs : 单例的初始化参数
"""
instances = {}
executor = ThreadPoolExecutor(1)
def __create_instance(*args, **kwargs) :
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
def get_instance (*args, **kwargs):
if cls in instances:
return instances[cls]
f = executor.submit(__create_instance, *args, **kwargs)
return f.result()
return get_instance
使用例子:
# 装饰器的单例,测试多线程安全
@singleton
class Foo(object):
def __init__(self,name):
self.name = name
import time
time.sleep(1)
def __str__(self):
return f"Foo object {self.name} at {id(self):#016X}"
第二种 基于元类来实现:
import threading
class SingletonType(type):
"""
基于元类(metaclass)来实现的线城安全的单例模式.
1.类由type创建,创建类时,type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)
2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法
"""
_instance_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
with SingletonType._instance_lock:
if not hasattr(cls, "_instance"):
cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
return cls._instance
# SingletonType使用示例:
class Foo(metaclass=SingletonType):
def __init__(self,name):
self.name = name
import time
time.sleep(1)
def __str__(self):
return f"Foo object {self.name} at {id(self):#016X}"