使用繼承並利用__new__
代碼實例
import threading
from time import sleep
class SingletonSample(object):
_instanceLock = threading.Lock()
_instance = {}
def __new__(cls, *args, **kwargs):
if cls not in cls._instance:
print("get here 1")
with cls._instanceLock:
if cls not in cls._instance:
print("get here 2")
cls._instance[cls] = super(SingletonSample, cls).__new__(cls, *args)
print cls._instance
return cls._instance[cls]
class SingletonSubA(SingletonSample):
pass
class SingletonSubB(SingletonSample):
pass
def task(index, obj, lock):
if obj == "A":
so = SingletonSubA()
else:
so = SingletonSubB()
sleep(2)
with lock:
print("In Thread %s-%s" % (obj, index), so)
if __name__ == "__main__":
print_lock = threading.Lock()
try:
error_so = SingletonSample()
for i in range(10):
thread = threading.Thread(target=task, name="thread-%d" % i, args=(i, "A", print_lock))
thread.start()
for i in range(10):
thread = threading.Thread(target=task, name="thread-%d" % i, args=(i, "B", print_lock))
thread.start()
except Exception as e:
print("ERROR, exception caught!Detail is: %s" % e)
執行一下:
C:\Python27\python.exe D:/代碼/python-DP/SingletonSample.py
get here 1
get here 2
{<class '__main__.SingletonSample'>: <__main__.SingletonSample object at 0x0335CE10>}
get here 1
get here 2
{<class '__main__.SingletonSample'>: <__main__.SingletonSample object at 0x0335CE10>, <class '__main__.SingletonSubA'>: <__main__.SingletonSubA object at 0x03377990>}
get here 1
get here 2
{<class '__main__.SingletonSubB'>: <__main__.SingletonSubB object at 0x033A8250>, <class '__main__.SingletonSample'>: <__main__.SingletonSample object at 0x0335CE10>, <class '__main__.SingletonSubA'>: <__main__.SingletonSubA object at 0x03377990>}
('In Thread A-2', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-0', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-1', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-4', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-5', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-3', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-7', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-6', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-9', <__main__.SingletonSubA object at 0x03377990>)
('In Thread A-8', <__main__.SingletonSubA object at 0x03377990>)
('In Thread B-0', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-1', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-2', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-3', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-4', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-5', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-6', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-8', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-9', <__main__.SingletonSubB object at 0x033A8250>)
('In Thread B-7', <__main__.SingletonSubB object at 0x033A8250>)
Process finished with exit code 0
使用元類metaclass以及__call__
import threading
import time
class MetaSingleton(type):
_instance = {}
lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if not cls._instance. has_key(cls):
print("Get here 1!")
with cls.lock:
if not cls._instance. has_key(cls):
print("Get here 2!")
cls._instance[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
print(cls._instance)
return cls._instance[cls]
class ConcreteSingleA(object):
__metaclass__ = MetaSingleton
def __init__(self, arg1, arg2):
print("Now enter in class ConcreteSingleA func __init__ ,arg1 is %s, arg2 is %s" % (arg1, arg2))
self.arg1 = arg1
self.arg2 = arg2
print("In __init__ arg1 is %s" % self.arg1)
print("In __init__ arg2 is %s" % self.arg2)
def task(arg1, arg2, lock_o):
so = ConcreteSingleA(arg1, arg2)
time.sleep(2)
with lock_o:
print so
print("In thread %s arg1 is %s" % (arg1, arg1))
print("In thread %s arg2 is %s" % (arg1, arg2))
if __name__ == "__main__":
print_lock = threading.Lock()
for i in range(0, 10):
thread = threading.Thread(target=task, name="Thread%d" % i, args=(str(i), "aa%s"%i, print_lock))
thread.start()
執行一下
C:\Python27\python.exe D:/代碼/python-DP/MetaClassSingletonSample.py
Get here 1!
Get here 2!
Now enter in class ConcreteSingleA func __init__ ,arg1 is 0, arg2 is aa0
In __init__ arg1 is 0
In __init__ arg2 is aa0Get here 1!
{<class '__main__.ConcreteSingleA'>: <__main__.ConcreteSingleA object at 0x033989B0>}
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 3 arg1 is 3
In thread 3 arg2 is aa3
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 2 arg1 is 2
In thread 2 arg2 is aa2
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 0 arg1 is 0
In thread 0 arg2 is aa0
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 1 arg1 is 1
In thread 1 arg2 is aa1
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 6 arg1 is 6
In thread 6 arg2 is aa6
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 5 arg1 is 5
In thread 5 arg2 is aa5
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 4 arg1 is 4
In thread 4 arg2 is aa4
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 8 arg1 is 8
In thread 8 arg2 is aa8
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 9 arg1 is 9
In thread 9 arg2 is aa9
<__main__.ConcreteSingleA object at 0x033989B0>
In thread 7 arg1 is 7
In thread 7 arg2 is aa7
Process finished with exit code 0